2014-09-01 13 views
5

Ich habe versucht zu verstehen, wie man mit der Ausgabe von strsplit ein bisschen besser umgehen. Ich habe oft Daten wie diese, die ich teilen wollen:Extrahieren nth Element aus einer verschachtelten Liste nach Strsplit - R

mydata <- c("144/4/5", "154/2", "146/3/5", "142", "143/4", "DNB", "90") 

#[1] "144/4/5" "154/2" "146/3/5" "142"  "143/4" "DNB"  "90"  

Nach Spaltung, dass die Ergebnisse sind wie folgt:

strsplit(mydata, "/") 

#[[1]] 
#[1] "144" "4" "5" 

#[[2]] 
#[1] "154" "2" 

#[[3]] 
#[1] "146" "3" "5" 

#[[4]] 
#[1] "142" 

#[[5]] 
#[1] "143" "4" 

#[[6]] 
#[1] "DNB" 

#[[7]] 
#[1] "90" 

Ich weiß von der strsplit Hilfe-Anleitung, die letzte leere Strings nicht erzeugt werden . Daher wird es 1, 2 oder 3 Elementen in jedem meiner Ergebnisse basierend auf der Anzahl von „/“ aufzuspalten von

das erste Element zu erhalten ist sehr trivial:

sapply(strsplit(mydata, "/"), "[[", 1) 

#[1] "144" "154" "146" "142" "143" "DNB" "90" 

Aber ich bin nicht sicher, wie man die 2., 3. ... bekommt, wenn es diese ungleiche Anzahl von Elementen in jedem Ergebnis gibt.

sapply(strsplit(mydata, "/"), "[[", 2) 

# Error in FUN(X[[4L]], ...) : subscript out of bounds 

Ich hoffe, von einer Arbeitslösung zurück, die folgenden:

#[1] "4" "2" "3" "NA" "4" "NA" "NA" 

Dies ist ein relativ kleines Beispiel ist. Ich konnte einige for-Schleife sehr einfach auf diesen Daten machen, aber für echte Daten mit 1000s von Beobachtungen, um den strsplit laufen zu lassen, und Dutzenden von Elementen, die daraus erzeugt wurden, hoffte ich, eine verallgemeinerbare Lösung zu finden.

+4

mit '[' statt '[[' hinzufügen scheint –

+0

zu funktionieren @alexis_laz Sie sollten diese eine Antwort machen. Ich kann das nicht in 'help (" [")' finden. – Roland

Antwort

4

(zumindest in Bezug auf 1D Vektoren) [ scheint NA zurückzukehren, wenn "i> Länge (x)", während [[ einen Fehler zurückgibt.

x = runif(5) 
x[6] 
#[1] NA 
x[[6]] 
#Error in x[[6]] : subscript out of bounds 

ein wenig Graben, do_subset_dflt (dh [) ruft ExtractSubset, wo wir feststellen, dass, wenn ein gesuchter Index („ii“) ist „> Länge (x)“ NA (ein wenig zu sauber geändert) zurückgegeben :

if(0 <= ii && ii < nx && ii != NA_INTEGER) 
    result[i] = x[ii]; 
else 
    result[i] = NA_INTEGER; 

Auf der anderen Seite do_subset2_dflt (dh[[) gibt einen Fehler, wenn der gewünschte Index ("Offset") ist "> Länge (x)" (modifizierte ein bisschen sauber sein):

if(offset < 0 || offset >= xlength(x)) { 
    if(offset < 0 && (isNewList(x)) ... 
    else errorcall(call, R_MSG_subs_o_b); 
} 

wo #define R_MSG_subs_o_b _("subscript out of bounds")

(Ich bin nicht sicher über die obigen Code-Schnipsel, aber sie scheinen relevant auf der Grundlage ihrer Rückgaben)

3

Versuchen Sie folgendes:

> read.table(text = mydata, sep = "/", as.is = TRUE, fill = TRUE) 
    V1 V2 V3 
1 144 4 5 
2 154 2 NA 
3 146 3 5 
4 142 NA NA 
5 143 4 NA 
6 DNB NA NA 
7 90 NA NA 

Wenn Sie DNB behandeln wollen wie ein NA dann na.strings="DNB" das Argument hinzufügen.

Wenn Sie wirklich strsplit dann versuchen, diese verwenden möchten:

> do.call(rbind, lapply(strsplit(mydata, "/"), function(x) head(c(x,NA,NA), 3))) 
    [,1] [,2] [,3] 
[1,] "144" "4" "5" 
[2,] "154" "2" NA 
[3,] "146" "3" "5" 
[4,] "142" NA NA 
[5,] "143" "4" NA 
[6,] "DNB" NA NA 
[7,] "90" NA NA 

Hinweis: alexis_laz Beobachtung Mit dass x[i] kehrt NA wenn i ist oben nicht in 1:length(x) die letzte Zeile Code vereinfacht werden könnte:

t(sapply(strsplit(mydata, "/"), "[", 1:3)) 
+1

In Bezug auf Ihren zweiten Ansatz: Verwenden Sie 'length <-' sollte vorzuziehen sein. 'nmax <- max (sapply (mysplitdata, length)); mysplitdata <- lapply (mysplitdata, "Länge <-", Wert = nmax) ' – Roland

1

Sie könnten regex verwenden (wenn es erlaubt ist)

library(stringr) 
str_extract(mydata , perl("(?<=\\d/)\\d+")) 
#[1] "4" "2" "3" NA "4" NA NA 
str_extract(mydata , perl("(?<=/\\d/)\\d+")) 
#[1] "5" NA "5" NA NA NA NA 
0

Sie können die Länge innerhalb sapply, was in NA, wo die aktuelle Länge ist kürzer als die zugewiesene Länge.

s <- strsplit(mydata, "/") 
sapply(s, function(x) { length(x) <- 3; x[2] }) 
# [1] "4" "2" "3" NA "4" NA NA 

Dann können Sie ein zweites Indexierungs Argument mit mapply

m <- max(sapply(s, length)) 
mapply(function(x, y, z) { length(x) <- z; x[y] }, s, 2, m) 
# [1] "4" "2" "3" NA "4" NA NA 
Verwandte Themen