2016-04-25 7 views
2

Ich habe einen Datenrahmen und ich versuche, den Datenrahmen zu durchlaufen, um diejenigen Spalten zu identifizieren, die ein Sonderzeichen enthalten oder die alle Großbuchstaben sind.Grabbing-Spalten mit Sonderzeichen und Großbuchstaben

Ich habe ein paar Dinge ausprobiert, aber nichts, wo ich Apple die Spaltennamen innerhalb der Schleife zu fangen bin.

data = data.frame(one=c(1,3,5,1,3,5,1,3,5,1,3,5), two=c(1,3,5,1,3,5,1,3,5,1,3,5), 
       thr=c("A","B","D","E","F","G","H","I","J","H","I","J"), 
       fou=c("A","B","D","A","B","D","A","B","D","A","B","D"), 
       fiv=c(1,3,5,1,3,5,1,3,5,1,3,5), 
       six=c("A","B","D","E","F","G","H","I","J","H","I","J"), 
       sev=c("A","B","D","A","B","D","A","B","D","A","B","D"), 
       eig=c("A","B","D","A","B","D","A","B","D","A","B","D"), 
       nin=c(1.24,3.52,5.33,1.44,3.11,5.33,1.55,3.66,5.33,1.32,3.54,5.77), 
       ten=c(1:12), 
       ele=rep(1,12), 
       twe=c(1,2,1,2,1,2,1,2,1,2,1,2), 
       thir=c("THiS","THAT34","T(&*(", "!!!","@$#","$Q%J","who","THIS","this","this","this","this"), 
       stringsAsFactors = FALSE) 
data 

colls <- c() 

    spec=c("$","%","&") 
    for(col in names(data)) { 
     if(length(strings[stringr::str_detect(data[,col], spec)]) >= 1){ 
      print("HORRAY") 
colls <- c(collls, col) 
     } 
     else print ("NOOOOOOOOOO") 
    } 


    for(col in names(data)) { 
     if(any(data[,col]) %in% spec){ 
     print("HORRAY") 
colls <- c(collls, col) 
     } 
     else print ("NOOOOOOOOOO") 
    } 

Kann jemand Licht auf eine gute Möglichkeit, dieses Problem anzugehen.

EDIT:

Das Endziel ist ein Vektor mit einem Namen von Spaltennamen zu haben, die die Kriterien erfüllen. Sorry für meine Frage SO schlecht, aber dies wird hoffentlich helfen, mit dem, was ich versuche

+0

Gibt es einen Sinn, die Daten in Spalten anstatt nur als Strings (eine Zeichenfolge pro Zeile) zu haben? – Gregor

+0

Das ist nur, wie die Daten sind, und ich muss auch die logischen, numerischen usw. Spalten durchlaufen. Ich schätze, dass ich sie extrahieren und als Vektor speichern könnte, aber am Ende des Tages ist es das Ziel, den Spaltennamen für die Variable zu erhalten, die ein Sonderzeichen enthält usw. – AGUY

+0

Normalerweise erhalten Sie bessere Ergebnisse, wenn Sie einschließen Dein Ziel am Ende des Tages in deiner Frage. – Gregor

Antwort

1

ich zusammenbrechen würde die Daten in Strings (eine Zeichenkette pro Zeile)

strings = apply(data, 1, paste, collapse = "") 
contains_only_caps = strings == toupper(strings) 
strings[contains_only_caps] 
# [1] "33BB3BBB3.52 212THAT34" "55DD5DDD5.33 311T(&*(" "11EA1EAA1.44 412!!!" "33FB3FBB3.11 [email protected]$#" 
# [5] "55GD5GDD5.33 612$Q%J" "33IB3IBB3.66 812THIS" 


# escaping special characters 
spec=c("\\$","%","\\&") 
contains_spec = stringr::str_detect(strings, pattern = paste(spec, collapse = "|")) 

strings[contains_spec] 
# [1] "55DD5DDD5.33 311T(&*(" "33FB3FBB3.11 [email protected]$#" "55GD5GDD5.33 612$Q%J" 

Sie auch which tun nutzen könnten auf contains_spec oder contains_only_caps, um die entsprechenden Zeilennummern für den ursprünglichen Datenrahmen zu erhalten. Ich denke, dass die Verwendung von Strings anstelle von zeilenweisen Datenrahmenelementen viel schneller ist - solange Sie die ganzen Strings durchsuchen wollen, nicht bestimmte Spalten für bestimmte Bedingungen.

2

Ich würde grep() verwenden, um nach dem Muster zu suchen, an dem Sie interessiert sind. Siehe here.

[:upper:] Entspricht allen Großbuchstaben.

Kombinieren Sie es mit Ankern (^, ​​$) und passen Sie ein oder mehrere Male (+) gibt ^[[:upper:]]+$ und sollte nur Einträge vollständig in Großbuchstaben übereinstimmen.

Die folgende würde die Sonderzeichen in Ihrem Spielzeug Daten übereinstimmen gesetzt (aber garantiert nicht alle Sonderzeichen in Ihrem realen Datensatz d.h Form übereinstimmen Feeds, Wagenrücklauf)

[:punct:] #Matches Zeichensetzung - "# $% & '() * +, - /:; < => @ [\]^_` {|} ~

Beachten Sie, dass anstatt [:punct:] verwenden Sie Ihre Sonderzeichen manuell definieren könnte.?..

Wir können den resultierenden Code auf der ersten Zeile Ihres Datensatzes versuchen.

#Using grepl() rather than grep() so that we return a list of logical values. 
grepl(x= data[1,], pattern = "^[[:upper:]]+$|[[:punct:]]") 
[1] FALSE FALSE TRUE TRUE FALSE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE 

Dies gibt uns unsere erwartete Antwort mit Ausnahme Spalte neun, die den Wert 1,24 hat hier das Komma erkannt wird als Satzzeichen und wird als Übereinstimmung gekennzeichnet Wir können eine "negative Lookahead Assertion" hinzufügen - (?!\\.) - um Zeiträume aus der Betrachtung zu entfernen, bevor sie überhaupt auf Interpunktionszeichen geprüft werden. Beachten Sie, dass wir \ verwenden, um der Periode zu entkommen.

grepl(x= data[1,], perl = TRUE, pattern = "(?!\\.)(^[[:upper:]]+$|[[:punct:]])") 
[1] FALSE FALSE TRUE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE TRUE 

Dies liefert eine bessere Antwort - es stimmt jetzt nicht mehr mit Nachkommastellen überein. Hinweis: Dies ist möglicherweise nicht das, was Sie möchten, da dieses Muster auch keinen vollständigen Stopps in Zeichenfeldern entspricht. Sie müssten das Muster weiter verfeinern.

Anstatt eine 'for-Schleife' zu verwenden, um diesen Code über jede Zeile in Ihrem Datenrahmen zu wiederholen, würde ich stattdessen die Vektorisierung verwenden, die 'mehr R wie' ist.

Um dies zu tun wir unser Skript in eine Funktion umwandeln müssen, die wir mit anwenden nennen()

myFunction <- function(x){ 
     matches <- grepl(x= x, perl = TRUE, pattern = "(?!\\.)(^[[:upper:]]+$|[[:punct:]])") 
    #Given a set of logical vectors 'matches', is at least one of the values true? using any() 
    return(any(matches)) 
} 

apply(X = data, 1, myFunction) 

Die 1 weist oben apply() über die Reihen zu wiederholen, anstatt Spalten.

In Ihrem Beispieldatensatz haben alle Zeilen einen Eintrag, der ein Sonderzeichen oder eine Zeichenfolge aller Großbuchstaben enthält. Dies ist nicht überraschend, da viele Spalten in Ihrem Beispieldatensatz eine Liste von einzelnen Großbuchstaben sind.

Wenn Sie nur daran interessiert sind, in der Werte in Spalte dreizehn passen die genannten Kriterien können Sie:

matches <- grepl(x= data$thir, perl = TRUE, pattern = "(?!\\.)(^[[:upper:]]+$|[[:punct:]])") 
matches 
[1] FALSE FALSE TRUE TRUE TRUE TRUE FALSE TRUE FALSE FALSE FALSE FALSE 

Um die Datenrahmen auf passende Zeilen Teilmenge:

data[matches,] 
    one two thr fou fiv six sev eig nin ten ele twe thir 
3 5 5 D D 5 D D D 5.33 3 1 1 T(&*(
4 1 1 E A 1 E A A 1.44 4 1 2 !!! 
5 3 3 F B 3 F B B 3.11 5 1 1 @$# 
6 5 5 G D 5 G D D 5.33 6 1 2 $Q%J 
8 3 3 I B 3 I B B 3.66 8 1 2 THIS 

Ihre Datenrahmen auf der Teilmenge Nicht übereinstimmende Zeilen:

data[!matches,] 
    one two thr fou fiv six sev eig nin ten ele twe thir 
1 1 1 A A 1 A A A 1.24 1 1 1 THiS 
2 3 3 B B 3 B B B 3.52 2 1 2 THAT34 
7 1 1 H A 1 H A A 1.55 7 1 1 who 
9 5 5 J D 5 J D D 5.33 9 1 1 this 
10 1 1 H A 1 H A A 1.32 10 1 2 this 
11 3 3 I B 3 I B B 3.54 11 1 1 this 
12 5 5 J D 5 J D D 5.77 12 1 2 this 

Beachten Sie, dass der verwendete reguläre Ausdruck nicht mit T übereinstimmt HAT34, da es nicht ausschließlich aus Großbuchstaben besteht und am Ende die Zahl 34 hat.

EDIT:

Um eine Liste der Spaltennamen zu erhalten Spalten zu identifizieren, die die Kriterien in Ihrer bearbeiten Verwendung myFunction oben beschrieben, mit erfüllen:

colnames(data)[apply(X = data, 2, myFunction)] 
"thr" "fou" "six" "sev" "eig" "thir" 

Die Zahl in apply() Änderungen von 1 bis 2 Spalten statt Zeilen wiederholen. Wir übergeben die Ausgabe von apply(), einer Liste logischer Übereinstimmungen (TRUE oder FALSE), an Spaltennamen (Daten) - dies gibt die übereinstimmenden Spaltennamen über eine Untermenge zurück.