2014-10-04 1 views
8

Ho un frame di dati costituito da due colonne: un vettore di caratteri col1 e una colonna list, col2.Unlist data frame column preserving information from other column

myVector <- c("A","B","C","D") 

myList <- list() 
myList[[1]] <- c(1, 4, 6, 7) 
myList[[2]] <- c(2, 7, 3) 
myList[[3]] <- c(5, 5, 3, 9, 6) 
myList[[4]] <- c(7, 9) 

myDataFrame <- data.frame(row = c(1,2,3,4)) 

myDataFrame$col1 <- myVector 
myDataFrame$col2 <- myList 

myDataFrame 
# row col1   col2 
# 1 1 A 1, 4, 6, 7 
# 2 2 B  2, 7, 3 
# 3 3 C 5, 5, 3, 9, 6 
# 4 4 D   7, 9 

voglio escludere dall'elenco mia col2 mantenendo per ogni elemento dei vettori nella lista le informazioni memorizzate nel col1. Per esprimerlo in modo diverso, nella terminologia di risagoma del frame dei dati comunemente usata: la colonna dell'elenco "wide" deve essere convertita in un formato "lungo".

Quindi alla fine della giornata voglio due vettori di lunghezza pari a length(unlist(myDataFrame$col2)). Nel codice:

# unlist myList 
unlist.col2 <- unlist(myDataFrame$col2) 
unlist.col2 
# [1] 1 4 6 7 2 7 3 5 5 3 9 6 7 9 

# unlist myVector to obtain 
# unlist.col1 <- ??? 
# unlist.col1 
# [1] A A A A B B B C C C C C D D 

Non riesco a pensare a un modo semplice per ottenerlo.

risposta

3

Qui, l'idea è quello di ottenere prima la lunghezza di ogni elemento di lista utilizzando sapply e quindi utilizzare rep per replicare il col1 con quella length

l1 <- sapply(myDataFrame$col2, length) 
    unlist.col1 <- rep(myDataFrame$col1, l1) 
    unlist.col1 
#[1] "A" "A" "A" "A" "B" "B" "B" "C" "C" "C" "C" "C" "D" "D" 

O come suggerito da @Ananda Mahto, quanto sopra potrebbe essere anche fatto con vapply

with(myDataFrame, rep(col1, vapply(col2, length, 1L))) 
    #[1] "A" "A" "A" "A" "B" "B" "B" "C" "C" "C" "C" "C" "D" "D" 
4

È possibile utilizzare la "data.table" per espandere l'intero data.frame, ed estrarre la colonna di interesse.

library(data.table) 
## expand the entire data.frame (uncomment to see) 
# as.data.table(myDataFrame)[, unlist(col2), by = list(row, col1)] 

## expand and select the column of interest: 
as.data.table(myDataFrame)[, unlist(col2), by = list(row, col1)]$col1 
# [1] "A" "A" "A" "A" "B" "B" "B" "C" "C" "C" "C" "C" "D" "D" 

Nelle versioni più recenti di R, è ora possibile utilizzare la funzione lengths invece dell'approccio sapply(list, length). La funzione lengths è notevolmente più veloce.

with(myDataFrame, rep(col1, lengths(col2))) 
# [1] "A" "A" "A" "A" "B" "B" "B" "C" "C" "C" "C" "C" "D" "D" 
15

Si può anche utilizzare unnest dal pacchetto tidyr:

library(tidyr) 
unnest(myDataFrame, col2) 

#  row col1 col2 
# (dbl) (chr) (dbl) 
# 1  1  A  1 
# 2  1  A  4 
# 3  1  A  6 
# 4  1  A  7 
# 5  2  B  2 
# 6  2  B  7 
# 7  2  B  3 
# 8  3  C  5 
# 9  3  C  5 
# 10  3  C  3 
# 11  3  C  9 
# 12  3  C  6 
# 13  4  D  7 
# 14  4  D  9