2011-12-11 11 views
10

Ho un set di dati con più colonne, una delle quali è una colonna per i tempi di reazione. Questi tempi di reazione sono separati da una virgola per indicare i tempi di reazione (dello stesso partecipante) per le diverse prove.Convertire la voce separata da virgola alle colonne

Ad esempio: riga 1 (cioè .: i dati dal partecipante 1) presenta le seguenti nella colonna "tempi di reazione"

reaction_times 
2000,1450,1800,2200 

Quindi questi sono i tempi di reazione del partecipante 1 per prove 1,2,3,4.

Ora desidero creare un nuovo set di dati in cui i tempi di reazione per queste prove formano tutti colonne individuali. In questo modo posso calcolare il tempo medio di reazione per ogni prova .

   trial 1 trial 2 trial 3 trial 4 
participant 1: 2000  1450  1800  2200 

ho provato il "colsplit" dal -package "reshape2", ma che non sembra per dividere i miei dati in nuove colonne (forse perché il mio dati sono tutti in 1 cella).

Qualche suggerimento?

risposta

17

Penso che stiate cercando la funzione strsplit();

a = "2000,1450,1800,2200" 
strsplit(a, ",") 
[[1]]                                      
[1] "2000" "1450" "1800" "2200" 

Si noti che strsplit restituisce un elenco, in questo caso con un solo elemento. Questo perché strsplit prende i vettori come input. Pertanto, puoi anche inserire un vettore lungo dei caratteri a cella singola nella funzione e recuperare un elenco diviso di quel vettore. In un esempio più rilevante questo aspetto come:

# Create some example data 
dat = data.frame(reaction_time = 
     apply(matrix(round(runif(100, 1, 2000)), 
        25, 4), 1, paste, collapse = ","), 
        stringsAsFactors=FALSE) 
splitdat = do.call("rbind", strsplit(dat$reaction_time, ",")) 
splitdat = data.frame(apply(splitdat, 2, as.numeric)) 
names(splitdat) = paste("trial", 1:4, sep = "") 
head(splitdat) 
    trial1 trial2 trial3 trial4 
1 597 1071 1430 997 
2 614 322 1242 1140 
3 1522 1679  51 1120 
4 225 1988 1938 1068 
5 621 623 1174  55 
6 1918 1828 136 1816 

e, infine, calcolare la media per persona:

apply(splitdat, 1, mean) 
[1] 1187.50 361.25 963.75 1017.00 916.25 1409.50 730.00 1310.75 1133.75 
[10] 851.25 914.75 881.25 889.00 1014.75 676.75 850.50 805.00 1460.00 
[19] 901.00 1443.50 507.25 691.50 1090.00 833.25 669.25 
+0

Wow, ottima e rapida risposta Paul, dankjewel!Funziona come un fascino :) Se non sbaglio, puoi anche usare "colMeans" e "rowMeans" invece di "apply (splitdat, 1, mean)"? PS. scusa non posso votarti, a quanto pare ho bisogno di 15 reputazione prima ?! – user1092247

+0

Hai ragione riguardo a colMeans ofcourse :). Penso comunque che usare apply sia anche bello perché è molto più flessibile. ps Sei anche tu dai Paesi Bassi? –

+0

Grazie! Sì, sono anche di NL :) – user1092247

8

Un ingegnoso, anche se piuttosto pesante, modo è quello di utilizzare read.csv in combinazione con textConnection. Supponendo che i vostri dati sono in un frame di dati, df:

x <- read.csv(textConnection(df[["reaction times"]])) 
+2

Non mi sembra affatto pesante. Sembra che maneggi R con un tocco abile. –

+0

Soluzione elegante! Sarebbe interessante vedere se il modo in cui le nostre soluzioni si confrontano in termini di velocità per dataset davvero grandi. –

+0

Funziona perfettamente (posso effettivamente approvare entrambi come soluzioni?) – user1092247

6

vecchia questione, ma mi sono imbattuto da another recent question (che sembra non correlato).

Entrambe le risposte esistenti sono appropriate, ma volevo condividere una risposta relativa a un pacchetto che ho creato chiamato "splitstackshape" che è veloce e ha una sintassi semplice.

Ecco alcuni dati di esempio:

Questa è la scissione:

library(splitstackshape) 
cSplit(dat, "reaction_time", ",") 
# reaction_time_1 reaction_time_2 reaction_time_3 reaction_time_4 
# 1:    532   1889   1374    761 
# 2:    745   1322    769   1555 
# 3:   1146   1259   1540   1869 
# 4:   1817    125    996    425 
# 5:    404    413   1436   1304 
# 6:   1797    354   1984    252 

e, facoltativamente, se avete bisogno di prendere la rowMeans:

rowMeans(cSplit(dat, "reaction_time", ",")) 
# [1] 1139.00 1097.75 1453.50 840.75 889.25 1096.75 
+0

Pacchetto eccellente: grazie per la condivisione, rende molto più semplice! – user1092247

2

Un'altra opzione utilizzando dplyr e tidyr con i dati di esempio di Paul Hiemstra è:

# create example data 
data = data.frame(reaction_time = 
        apply(matrix(round(runif(100, 1, 2000)), 
            25, 4), 1, paste, collapse = ","), 
      stringsAsFactors=FALSE) 
head(data) 

# clean data 
data2 <- data %>% mutate(split_reaction_time = str_split(as.character(reaction_time), ",")) %>% unnest(split_reaction_time) 
data2$col_names <- c("trial1", "trial2", "trial3", "trial4") 
data2 <- data2 %>% spread(key = col_names, value = split_reaction_time) %>% select(-reaction_time) 
head(data2) 
Problemi correlati