2016-06-09 5 views
3

Ich habe eine data.table mit vielen fehlenden Werten und ich möchte eine Variable, die mir eine 1 für den ersten Nicht-Missin-Wert in jeder Gruppe gibt.R: finde die erste Nicht-NA-Beobachtung in der Spalte data.table nach Gruppe

Say I haben eine so data.table:

library(data.table) 
DT <- data.table(iris)[,.(Petal.Width,Species)] 
DT[c(1:10,15,45:50,51:70,101:134),Petal.Width:=NA] 

die nun Missings am Anfang, am Ende und dazwischen. Ich habe zwei Versionen ausprobiert, ist:

DT[min(which(!is.na(Petal.Width))),first_available:=1,by=Species] 

aber es findet nur das globale Minimum (in diesem Fall setosa die richtigen 1 wird), nicht das Minimum von Gruppe. Ich denke, das ist der Fall, weil data.table ersten Teilmengen von i, dann sortiert nach Gruppe, richtig? Es wird also nur mit der Zeile funktionieren, die das globale Minimum von which(!is.na(Petal.Width)) ist, was der erste Nicht-NA-Wert ist.

Ein zweiter Versuch mit dem Test in j:

DT[,first_available:= ifelse(min(which(!is.na(Petal.Width))),1,0),by=Species] 

die nur eine Spalte von 1s zurückgibt. Hier habe ich keine gute Erklärung, warum es nicht funktioniert.

mein Ziel ist es dies:

DT[,first_available:=0] 
DT[c(11,71,135),first_available:=1] 

aber in Wirklichkeit Ich habe Hunderte von Gruppen. Jede Hilfe wäre willkommen!

Edit: this Frage kommt nahe, aber ist nicht auf NA ausgerichtet und löst das Problem hier nicht, wenn ich es richtig verstehe. Ich habe versucht:

DT <- data.table(DT, key = c('Species')) 
DT[unique(DT[,key(DT), with = FALSE]), mult = 'first'] 
+2

Mögliche doppelte o f [R: erste Beobachtung nach Gruppe mit data.table & self-join] (http://stackoverflow.com/questions/15776064/r-first-observation-by-group-using-data-table-self-join) – mtoto

+0

siehe bearbeiten, ich bin mir nicht sicher –

Antwort

6

Hier ist eine Art und Weise:

DT[!is.na(Petal.Width), first := as.integer(seq_len(.N) == 1L), by = Species] 
+0

nice, dieser behält auch NA's dazwischen, das könnte praktisch sein –

+0

Hey sieht gut aus, kannst du diesen Teil deines Codes erklären 'seq_len (.N)' –

+1

'.N' ist ein spezielles Symbol, das die Nummer von Beobachtungen für jede Gruppe. Und 'seq_len' konstruiert eine Sequenz von 1 bis .N. Siehe '? Data.table' für' .N' und andere spezielle Symbole und '? Seq_len' für mehr. – Arun

2

Wir

DT[DT[, .I[which.max(!is.na(Petal.Width))] , Species]$V1, 
    first_available := 1][is.na(first_available), first_available := 0] 

versuchen oder eine etwas kompaktere Option ist

DT[, first_available := as.integer(1:nrow(DT) %in% 
     DT[, .I[!is.na(Petal.Width)][1L], by = Species]$V1)][] 
+1

groß, das macht, was ich suche. Ich werde aufholen. Ich und 1L –

-1
> DT[!is.na(DT$Petal.Width) & DT$first_available == 1] 
    #  Petal.Width Species first_available 
    # 1:   0.2  setosa    1 
    # 2:   1.8 versicolor    1 
    # 3:   1.4 virginica    1 

    > rownames(DT)[!is.na(DT$Petal.Width) & DT$first_available == 1] 
    # [1] "11" "71" "135" 

    > rownames(DT)[!is.na(DT$Petal.Width) & DT$first_available == 0] 
    # [1] "12" "13" "14" "16" "17" "18" "19" "20" "21" "22" "23" "24" 
    # [13] "25" "26" "27" "28" "29" "30" "31" "32" "33" "34" "35" "36" 
    # [25] "37" "38" "39" "40" "41" "42" "43" "44" "72" "73" "74" "75" 
    # [37] "76" "77" "78" "79" "80" "81" "82" "83" "84" "85" "86" "87" 
    # [49] "88" "89" "90" "91" "92" "93" "94" "95" "96" "97" "98" "99" 
    # [61] "100" "136" "137" "138" "139" "140" "141" "142" "143" "144" "145" "146" 
    # [73] "147" "148" "149" "150" 
+1

aber das geht davon aus, dass ich bereits die Antwort habe, nicht? 'first_available' ist das, was ich versuche zu bekommen. Ich habe es am Ende manuell erstellt, um zu zeigen, wonach ich strebe. –

+1

auch, ist es nicht als schlechter Stil, 'data.table' und' dat.frame' Syntax zu mischen? Ich tue es hin und wieder auch aus Gründen der Einfachheit, also bin ich mir nicht sicher. Was denken Sie? –

+1

Ups, nur überprüft. Ich habe dein erstes Mal versucht und dann war es in DT, Meine Dummheit. Ich mache mit dem Dataframe Weg. Bearbeiten Sie meine Antwort in einer Weile. –

Verwandte Themen