2015-05-13 7 views
8

Ich suchte nach einer Möglichkeit, den Inhalt der Spalte durch ein Trennzeichen zu trennen und eine Tabelle in ein langes Format zu konvertieren. Ich fand cSplit aus dem splitstackshape Paket und es ist fast das, was ich gesucht habe.cSplit Bibliothek (splitstackshape) ist immer die Spalte

Problem ist jetzt mit der drop Option. Ich habe erwartet, dass meine Split-Spalte in gewisser Weise kopiert wird, aber das passiert nicht. Mache ich es falsch? Jemand hat das Problem erlebt?

Ich bin mir nicht sicher, ob ich etwas falsch mache, aber die Option drop = FALSE funktioniert nicht in meinem Fall. Hier

ein Beispiel:

library(splitstackshape) 
jnk <- data.table(a = '1,2,3,4,5', b = 5) 
jnk 
#   a b 
# 1: 1,2,3,4,5 5 

cSplit(jnk, 'a', ',', 'long', drop = FALSE) 
# a b 
# 1: 1 5 
# 2: 2 5 
# 3: 3 5 
# 4: 4 5 
# 5: 5 5 

Was erwartete ich so etwas wie das war:

cSplit(jnk, 'a', ',', 'long', drop = FALSE) 
# a b a.orig 
# 1: 1 5 1,2,3,4,5 
# 2: 2 5 1,2,3,4,5 
# 3: 3 5 1,2,3,4,5 
# 4: 4 5 1,2,3,4,5 
# 5: 5 5 1,2,3,4,5 

Ich bin mit der Version 1.4.2

+0

Dies sicher nicht funktionieren, wenn es mehr Zeilen in der df sind, da die 'jnk [[‚a‘]] die gleiche Länge haben' braucht oder es wird jedes Mal angehängt ... So ist es arbeitet nicht mit 'jnk <- data.table (a = c ('1,2,3,4,5', '1,2,3', '2,3'), b = c (5,4 , 3)) ' – drmariod

Antwort

10

Die "lange" Format ändert die Spalte an Stelle mit list(unlist(...)) in "data.table", zugewiesen mit :=. Wenn also drop verwendet würde, würden Sie die Spalte aufteilen und dann entfernen!

Ich werde versuchen, es explizit in der Dokumentation zu machen, dass drop nur für das wide Format ist, oder ein message hinzufügen, wenn ein Benutzer drop im langen Format zu verwenden versucht. Fühlen Sie sich frei zu file a FR or submit a PR.

Die Abhilfe wäre eine weitere Spalte zuweisen (zum Beispiel „a_orig“) und führen Sie dann die Spaltung:

jnk <- data.table(a=c('1,2,3,4,5','1,2,3','2,3'),b=c(5,4,3)) 
cSplit(jnk[, a_orig := a], "a", ",", "long") 
#  a b a_orig 
# 1: 1 5 1,2,3,4,5 
# 2: 2 5 1,2,3,4,5 
# 3: 3 5 1,2,3,4,5 
# 4: 4 5 1,2,3,4,5 
# 5: 5 5 1,2,3,4,5 
# 6: 1 4  1,2,3 
# 7: 2 4  1,2,3 
# 8: 3 4  1,2,3 
# 9: 2 3  2,3 
# 10: 3 3  2,3 

Ich habe ausführlich nicht getestet, aber eine mögliche Lösung könnte sein:

cSplit2 <- function(indt, splitCols, sep = ",", direction = "wide", 
        fixed = TRUE, drop = TRUE, stripWhite = TRUE, 
        makeEqual = NULL, type.convert = TRUE) { 
    if (direction == "long" & !drop) { 
    indt <- as.data.table(indt) 
    indt[, `:=`(eval(paste(splitCols, "orig", sep = "_")), 
       lapply(splitCols, function(x) indt[[x]]))] 
    } 
    cSplit(indt, splitCols, sep, direction, fixed, drop, stripWhite, 
     makeEqual, type.convert) 
} 

die Grundidee ist, nur dann, wenn direction == "wide" und drop = FALSE den Eingabedatensatz zu ändern. Dies ist ähnlich der Idee, die Sie hatten, aber kann möglicherweise die Lösung in das eigentliche Paket integriert werden, irgendwo um line 94. In diesem Fall sollte nur der indt[, `:=`(eval(paste(splitCols, "orig", sep = "_")), lapply(splitCols, function(x) indt[[x]]))] Teil notwendig sein.

0

Danke für die Rückmeldung, ich schrieb eine kleine Funktion als Workaround. Ich musste die data.table in data.frame ändern, damit es richtig funktioniert. Im Fall der data.table muss ich einen zusätzlichen Parameter setzen, aber es stürzt mit data.frame ab. In meinem Fall brauche ich die meiste Zeit data.frame, also habe ich es dafür optimiert.

library(splitstackshape) 
jnk <- data.frame(a = c('1,2,3,4,5','1,2,3','2,3'), 
        b = c('a,b,c,d,e','a,b,c','a,b'), 
        c = c(5,4,3)) 
jnk 

myCSplit <- function(data_set, splitCols, sep = ',', direction = 'long', drop = TRUE, ...) { 
    if(direction == 'long' & !drop) { 
    orig_names <- sub('$', '_orig', splitCols) 
    df <- as.data.frame(data_set[,splitCols]) 
    names(df) <- orig_names 
    df2 <- cbind(data_set, df) 
    return(cSplit(df2, splitCols, sep, 'long')) 
    } else { 
    return(cSplit(data_set, splitCols, sep, direction, drop = drop,...)) 
    } 
} 
myCSplit(jnk, 'a', ',') 
myCSplit(jnk, 'a', ',', drop = FALSE) 
myCSplit(jnk, 'a', ',', 'wide') 
myCSplit(jnk, 'a', ',', 'wide', drop = FALSE) 
myCSplit(jnk, c('a','b'), ',', 'long', drop = FALSE) 
+2

Lassen Sie mich vom Mittagessen mit einem allgemeineren Workaround zurückkommen. – A5C1D2H2I1M1N2O1R2T1

+0

Hey @AnandaMahto vielleicht könntest du diese Funktion der nächsten Version hinzufügen ... In meinem Fall wäre es sehr nützlich. – drmariod

+2

Soweit ich das beurteilen kann, sollte es mir möglich sein, den Fehler mit nur einer Zeile zu beheben. Ich werde einige Tests machen müssen, um es zu sehen. – A5C1D2H2I1M1N2O1R2T1