2017-01-21 3 views
5

Ich versuche, ein Dataset zu unterteilen, indem Sie einige Spalten aus einer data.table auswählen. Mein Code funktioniert jedoch nicht mit einigen Variationen. HierSubsetting-Spalten mit data.table in R

ist eine Probe data.table

library(data.table) 
DT <- data.table(ID = 1:50, 
      Capacity = sample(100:1000, size = 50, replace = F), 
      Code = sample(LETTERS[1:4], 50, replace = T), 
      State = rep(c("Alabama","Indiana","Texas","Nevada"), 50)) 

hier ein Arbeits Subset-Code ist:

DT[,1:2] 

Und hier ist ein Stück Code, das nicht funktioniert. Beachten Sie, dass dies mit einem Datenrahmen, aber nicht mit einer data.table funktioniert.

DT[,seq(1:2)] 

Ich brauche etwas entlang der Linien des zweiten Formats, weil ich auf der Ausgabe von grep basiert Subsetting() und es gibt die gleiche Leistung wie das zweite Format. Was mache ich falsch?

Danke!

+0

Die Verwendung von 'mit = FALSE' macht den zweiten funktioniert, aber ich weiß nicht, warum es nicht in erster Linie funktioniert. –

+2

@RichScriven danke für den Zeiger! Mit dieser Methode habe ich tiefer geforscht mit? Data.table. Diese Zeile scheint zu zeigen, warum. "Wenn mit = FALSE, kann j nur ein Vektor von Spaltennamen oder Positionen sein, die ausgewählt werden sollen (wie in data.frame).". – Naumz

+0

@RichScriven siehe [Antwort unten] (http://StackOverflow.com/a/41781264/2761575) Warum ':' funktioniert, aber 'seq' nicht – dww

Antwort

3

Auf neuere Versionen von data.table können Zahlen in j verwendet werden Spalten angeben Dieses Verhalten umfasst Formate wie DT[,1:2], um einen numerischen Bereich von Spalten anzugeben. (Beachten Sie, dass diese Syntax bei älteren Versionen von data.table nicht funktioniert).

Warum funktioniert DT[,1:2] funktioniert, aber DT[,seq(1:2)] nicht?Die Antwort ist für data.table:::[.data.table im Code begraben, die die Linien enthält:

if (!missing(j)) { 
    jsub = replace_dot_alias(substitute(j)) 
    root = if (is.call(jsub)) 
     as.character(jsub[[1L]])[1L] 
    else "" 
    if (root == ":" || (root %chin% c("-", "!") && is.call(jsub[[2L]]) && 
     jsub[[2L]][[1L]] == "(" && is.call(jsub[[2L]][[2L]]) && 
     jsub[[2L]][[2L]][[1L]] == ":") || (!length(all.vars(jsub)) && 
      root %chin% c("", "c", "paste", "paste0", "-", "!") && 
      missing(by))) { 
     with = FALSE 
    } 

Wir können hier sehen, dass data.table automatisch den with = FALSE Parameter für Sie setzt, wenn es die Verwendung von Funktions : in j erkennt. Es hat nicht die gleiche Funktionalität, die für seq eingebaut ist, also müssen wir mit = FALSE selbst spezifizieren, wenn wir die seq Syntax verwenden möchten.

DT[,seq(1:2), with=FALSE] 
+0

Ich denke, es wäre hilfreicher, den OP und andere Leser (wie mich) an einen relevanten Ort in den Dokumenten und/oder NEWS zu verweisen. – Frank

+0

@Frank Ich bin mir nicht sicher, dass dies tatsächlich irgendwo dokumentiert ist. Ich musste in den Quellcode schauen, um den Grund zu finden .... – dww

+1

Item # 3 in den 1.9.8 Release Notes deckt es ab. Ich nahm nur an, dass sie die Dokumente aktualisiert haben, um die Änderung widerzuspiegeln: https://github.com/Rdatatable/data.table/blob/master/NEWS.md#changes-in-v198--on-cran-25-nov-2016 – Frank

3

Das Hauptproblem hier ist, dass Spalten in data.table referenzierte Objekte sind, so dass Sie nicht die gleiche Syntax wie data.frame verwenden können. dh keine in Anführungszeichen gesetzten Namen oder Nummern

so DT[,c("ID", "Capacity")] wird nicht funktionieren aus dem gleichen Grund, dass DT[,seq(1:2)] wird nicht funktionieren.

jedoch ,with=FALSE Zugabe bewirkt, dass die data.table referenziert werden arbeiten, wie ein data.frame Sie

so DT[,c("ID", "Capacity"), with=FALSE] UND DT[,seq(1:2), with=FALSE] jetzt geben würde, was Sie wollen.

 ID Capacity 
    1: 1  913 
    2: 2  602 
    3: 3  861 
    4: 4  967 
    5: 5  374 
---    
196: 46  163 
197: 47  254 
198: 48  390 
199: 49  853 
200: 50  486 

EDIT: wie von @Rich Scriven

+0

Danke! Eine Frage aber. Ist seq (1: 2) nicht dasselbe wie 1: 2 für die Untermenge? Ich bin neugierig, weil einer arbeitet, und der andere nicht. – Naumz

+0

ehrlich gesagt nicht ganz sicher, was der Unterschied ist. Auch nicht sicher, warum 1: 2 für Sie funktioniert, weil es für mich nicht funktioniert. In jedem Fall funktioniert die Verwendung von = FALSE zusammen mit grep wie gewünscht. – JustGettinStarted

+1

'DT [, c (" ID "," Kapazität ")] arbeitet mit der neuesten Version von data.table. Das gleiche gilt für 'DT [, 1: 2]', und deshalb wurde mir gesagt, dass 'DT [, seq (1, 2)]' nicht funktioniert. –

5

Die Lektion, die ich ist list stattdessen verwenden gelernt wies darauf hin, von c:

DT[ ,list(ID,Capacity)] 
#--------------------------- 
    ID Capacity 
    1: 1  483 
    2: 2  703 
    3: 3  924 
    4: 4  267 
    5: 5  588 
---    
196: 46  761 
197: 47  584 
198: 48  402 
199: 49  416 
200: 50  130 

Damit können Sie die lästigen Zitate ignorieren, und es auch versetzt Sie in die Richtung, das j-Argument als ausgewerteten Ausdruck mit einer Umgebung der Datentabelle selbst zu sehen.

Um die benannten Spalten nach Nummer zu erhalten, verwenden Sie die mget Funktion und die names Funktion. R 'Namen' sind Sprachelemente, d. H. Datenobjekte im Suchpfad von der aktuellen Umgebung. Spaltennamen von Datenrahmen sind eigentlich nicht R names. Sie benötigen also eine Funktion, die einen Zeichenwert annimmt und den Interpreter dazu veranlasst, sie als vollqualifizierten name zu betrachten. Datatable - [- Funktion Syntax für den j Punkt tut Spaltennamen handhaben als die Sprache eher als Charakterwert Objekte als wären die [.data.frame -function:

DT[ ,mget(names(DT)[c(1,2)])] 
    ID Capacity 
    1: 1  483 
    2: 2  703 
    3: 3  924 
    4: 4  267 
    5: 5  588 
---    
196: 46  761 
197: 47  584 
198: 48  402 
199: 49  416 
200: 50  130 
+0

Ich mag 'list' auch, wenn das OP plant, Spalten mit grep auszuwählen, schlug ich mit = FALSE vor kompatibel damit. Aber Liste erfasst sicher die Bedeutung von data.table besser – JustGettinStarted

+0

@ 42-, danke für Ihre Antwort! Wie würde ich mit dem Listenansatz auf die Spalten anhand ihrer Indizes zugreifen, im Gegensatz zu den Namen? DT [, list (c (1,2))] scheint auch nicht zu funktionieren. – Naumz

+1

c (1,2) bewertet nichts Nützliches. Kann auch mit "get" oder "mget" zu "Sprach" -Werten zurückverwandelt werden. Siehe oben. –