2013-05-07 10 views
6

ho un dataframe che include una colonna di numeri in questo modo:suddivisione di un testo lungo in stringhe più piccole

360010001001002 
360010001001004 
360010001001005 
360010001001006 

vorrei spezzare in blocchi di 2 cifre, 3 cifre, 5 cifre, 1 digit , 4 cifre:

36 001 00010 0 1002 
36 001 00010 0 1004 
36 001 00010 0 1005 
36 001 00010 0 1006 

che sembra che dovrebbe essere semplice, ma sto leggendo la documentazione strsplit e non posso risolvere come mi piacerebbe fare questo lunghezze.

+0

È il vostro intento principale a) per convertire un ** vettore di lunghezze di sottostringa in coppie di indici ** o b) ** suddivisione in df colonne, e facendo ciò in modo efficiente **: rompere i blocchi come nuovi separati d.f. colonne (-> ddply (transform, ...)), o semplicemente manipolare le stringhe (ad esempio inserire '-') sulla stessa colonna? (-> ldply) – smci

+0

Il mio problema è risolto da tempo, ma da quando hai chiesto ... sì: volevo quei blocchi come colonne separate. Sono un numero identificativo. Dovrei tornare indietro e guardare esattamente, ma i blocchi hanno un significato: '36' è stato, contea' 001', blocco '00010' o qualcosa del genere. – Amanda

+0

Giusto, ma la mia domanda a) era che non ti importa se specifichi un vettore arbitrario di 'widths = c (2,3,5,1,4)' piuttosto che semplici vecchie coppie di indici: (1 , 2), (3,5), (6,10), (11,11), (12,15). Diversi rispondenti si sono appellati sul fatto che l'aritmetica degli indici cumulativi fosse una parte fondamentale della domanda. Si scopre che non lo era. Puoi riformulare per chiarezza. – smci

risposta

4

Assumendo questi dati:

x <- c("360010001001002", "360010001001004", "360010001001005", "360010001001006") 

prova this:

read.fwf(textConnection(x), widths = c(2, 3, 5, 1, 4)) 

Se x è numerico, sostituire x con as.character(x) in questa istruzione.

+0

+1 - abbastanza bello! Lo ricorderò. – Arun

+0

Mi sono liberato di questo: 'foo $ county_id <- as.vector (gsub (pippo $ fullfipsid, pattern =" .. (...). * ", Replace =" \\ 1 "))' per ogni blocco . Lavorato. Ma sto accettando questa risposta b/c è elegante e funziona anche. (L'ho provato) – Amanda

8

È possibile utilizzare substring (assumendo che la lunghezza della stringa/numero è fisso):

xx <- c(360010001001002, 360010001001004, 360010001001005, 360010001001006) 
out <- do.call(rbind, lapply(xx, function(x) as.numeric(substring(x, 
        c(1,3,6,11,12), c(2,5,10,11,15))))) 
out <- as.data.frame(out) 
+0

'ddply (muta ...)' sembra più elegante di 'do.call (rbind, ...)'? Vedi la mia risposta qui sotto. – smci

+0

e 'cumsum()' per accumulare gli indici – smci

4

Una versione funzionale:

split.fixed.len <- function(x, lengths) { 
    cum.len <- c(0, cumsum(lengths)) 
    start <- head(cum.len, -1) + 1 
    stop <- tail(cum.len, -1) 
    mapply(substring, list(x), start, stop) 
}  

a <- c(360010001001002, 
     360010001001004, 
     360010001001005, 
     360010001001006) 

split.fixed.len(a, c(2, 3, 5, 1, 4)) 
#  [,1] [,2] [,3] [,4] [,5] 
# [1,] "36" "001" "00010" "0" "1002" 
# [2,] "36" "001" "00010" "0" "1004" 
# [3,] "36" "001" "00010" "0" "1005" 
# [4,] "36" "001" "00010" "0" "1006" 
+0

+1 - uso piacevole (come al solito) di mapply qui! :) – Arun

0

(Wow, questo compito è incredibilmente goffo e doloroso rispetto a Python. Anyhoo ...)

PS Vedo ora il vostro intento principale era quello di trasformare un vettore di stringa lunghezze in coppie di indici. Si potrebbe utilizzare cumsum(), quindi ordinare gli indici tutti insieme:

ll <- c(2,3,5,1,4) 
sort(c(1, cumsum(ll), (cumsum(ll)+1)[1:(length(ll)-1)])) 
# now extract these as pairs. 

Ma è molto doloroso. La risposta di flodel è migliore.

Per quanto riguarda il compito effettivo di scissione in d.f. colonne e farlo in modo efficiente:

stringr::str_sub() abbina elegantemente con plyr::ddply()/ldply

require(plyr) 
require(stringr) 

df <- data.frame(value=c(360010001001002,360010001001004,360010001001005,360010001001006)) 
df$valc = as.character(df$value) 

df <- ddply(df, .(value), mutate, chk1=str_sub(valc,1,2), chk3=str_sub(valc,3,5), chk6=str_sub(valc,6,10), chk11=str_sub(valc,11,11), chk14=str_sub(valc,12,15)) 

#    value   valc chk1 chk3 chk6 chk11 chk14 
# 1 360010001001002 360010001001002 36 001 00010  0 1002 
# 2 360010001001004 360010001001004 36 001 00010  0 1004 
# 3 360010001001005 360010001001005 36 001 00010  0 1005 
# 4 360010001001006 360010001001006 36 001 00010  0 1006 
0

È possibile utilizzare questa funzione dal stringi pacchetto

splitpoints <- cumsum(c(2, 3, 5, 1,4)) 
stri_sub("360010001001002",c(1,splitpoints[-length(splitpoints)]+1),splitpoints) 
Problemi correlati