2014-09-01 11 views
5

Ho cercato di capire come gestire l'output di strsplit un po 'meglio. Ho spesso dati come questo che desidero dividere:Estrazione dell'nimo elemento da un elenco nidificato successivo a 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"  

Dopo la scissione che i risultati sono i seguenti:

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" 

So dalla guida aiuto strsplit che le stringhe vuote finali non sono prodotti . Pertanto, ci sarà 1, 2 o 3 elementi in ciascuno dei miei risultati in base al numero di "/" per raggruppati per

Ottenere il primo elemento è molto banale:

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

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

Ma io non sono certo come ottenere il 2 °, 3 ° ... quando ci sono questi numeri diversi di elementi in ogni risultato.

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

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

mi auguro di tornare da una soluzione di lavoro, quanto segue:

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

Questo è un relativamente piccolo esempio. Potrei fare un po 'di loop molto facilmente su questi dati, ma per dati reali con migliaia di osservazioni per eseguire lo strsplit su e dozzine di elementi prodotti da quello, speravo di trovare una soluzione più generalizzabile.

+4

Usando '[' invece di '[[' sembra funzionare –

+0

@alexis_laz Si dovrebbe fare questo una risposta. Non riesco a trovarlo in 'help (" [")'. – Roland

risposta

4

(almeno per quanto riguarda i vettori 1D) [ sembra tornare NA quando "i> lunghezza (x)", mentre [[ restituisce un errore.

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

Scavando un po ', do_subset_dflt (cioè [) chiama ExtractSubset dove notiamo che quando un indice voluto ("II") è "> lunghezza (x)" NA viene restituito (un po' modificato per essere pulito) :

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

D'altra parte do_subset2_dflt (ie[[) restituisce un errore se l'indice desiderato ("offset") è "> lunghezza (x)" (modificato un po 'per essere pulita):

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

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

(non sono sicuro sui frammenti di codice sopra riportati ma sembrano pertinenti in base ai loro ritorni)

3

Prova questa:

> 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 

Se si desidera trattare DNB come NA quindi aggiungere l'argomento na.strings="DNB".

Se davvero si vuole utilizzare strsplit quindi provare questo:

> 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 

Nota: Utilizzando l'osservazione di alexis_laz che x[i] restituisce NA se i non è in 1:length(x) l'ultima riga di codice di cui sopra potrebbe essere semplificata per:

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

Per quanto riguarda il secondo approccio: l'uso di 'length <-' dovrebbe essere preferibile. 'nmax <- max (sapply (mysplitdata, length)); mysplitdata <- lapply (mysplitdata, "length <-", value = nmax) ' – Roland

1

si potrebbe utilizzare regex (se è permesso)

0.123.
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

È possibile assegnare la lunghezza all'interno di sapply, con conseguente NA in cui la lunghezza corrente è inferiore alla lunghezza assegnata.

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

Quindi è possibile aggiungere un secondo argomento indicizzazione con 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 
Problemi correlati