2012-05-03 7 views
21

Estoy buscando una manera rápida de conseguir ida y vuelta entre una lista con el siguiente formato:lista llamada a/desde hoja.de.datos

$`a` 
    [1] 1 2 3 
$`b` 
    [1] 4 5 6 

a/desde un hoja.de.datos con el siguiente formato :

name x 
1 a 1 
2 a 2 
3 a 3 
4 b 4 
5 b 5 
6 b 6 

(no me importa lo que los nombres de las columnas son, en este caso.)

Aquí está la trama de datos se ha usado anteriormente en I-formato:

df <- data.frame(name=c(rep("a",3),rep("b",3)), x=c(1:3,4:6)) 

De nuevo, estoy buscando dos operaciones separadas: una para convertir el data.frame anterior a una lista, y otra para convertirlo de nuevo a un data.frame.

Respuesta

26

Uso stack y unstack de la base de R:

x <- data.frame(a=1:3, b=4:6) 

x 
    a b 
1 1 4 
2 2 5 
3 3 6 

Uso stack a de gran angular a de altura, es decir apilar los vectores en la parte superior de uno al otro.

y <- stack(x) 
y 
    values ind 
1  1 a 
2  2 a 
3  3 a 
4  4 b 
5  5 b 
6  6 b 

Usapara hacer el retroceso.

unstack(y) 
    a b 
1 1 4 
2 2 5 
3 3 6 

Si la estructura de datos es más complicado de lo que describes, stack y unstack posible que ya no sea adecuado. En ese caso, deberá usar reshape en la base R o melt y dcast en el paquete reshape2.

7

Tal vez algo como:

X <- split(df$x, df$name) 
data.frame(name = rep(names(X), sapply(X, length)), 
    x=do.call('c', X)) 

EDIT:decidí combinar solución Andrie y de que en uno que parece ser exactamente lo que pidió el PO bastante simple. Dicho esto, no entiendo muy bien una situación en la que trataría los datos de esta manera en lugar de cómo lo hizo Andrie, ya que un marco de datos es una lista de vectores de igual longitud de todos modos.

# Your data set 
df <- data.frame(name=c(rep("a",3),rep("b",3)), x=c(1:3,4:6)) 

# converting it to list of vectors 
X <- split(df[, 2], df[, 1]) 
# converting it to a dataframe 
Y <- stack(X)[, 2:1]; names(Y) <- names(df) 

# Take Y and feed it back to these lines to show it 
# switches back and forth 
(X <- split(Y[, 2], Y[, 1])) 
Y <- stack(X)[, 2:1]; names(Y) <- names(df);Y 
+0

+1 Estaba pensando en 'fundir (como .data.frame (...), value.name = 'x', variable.name = 'name')' para volver al marco de datos. – joran

+0

. Se debe tener en cuenta que la división reordena el marco de datos, ya que crea un factor del segundo vector. Véase también [Creación de una lista con nombre de dos vectores (nombres, valores)] (http://stackoverflow.com/questions/17842705/creating-a-named-list-from-two-vectors-names-values) para una solución usando 'mapply'. – jnas

2

quisiera hacer la observación de esperar no trivial que la sugerencia del @Tyler Rinker

X <- split(df$x, df$name) 

se puede hacer de manera más general con

X <- split(df, df$name) 

división de @Tyler Rinker() explicación coincide con el libro de cocina de I

http://my.safaribooksonline.com/book/programming/r/9780596809287/6dot1dot-splitting-a-vector-into-groups/id3392005

specifyin g que un vector se puede agrupar, mientras que de hecho se puede agrupar todo el marco de datos. Creo que agrupar el marco de datos, no el vector, sería la herramienta más valiosa (y de hecho lo que me trajo a esta publicación).

(df <- data.frame(name=c(rep("a",3),rep("b",3), rep("c",3)), x=c(1:3,4:6, 7:9))) 
(X <- split(df, df$name)) 

HTH.

Cuestiones relacionadas