Divida un marco de datos grande en una lista de marcos de datos basados en el valor común en la columna
performance matrix (2)
Tengo un marco de datos con 10 columnas, recopilando acciones de "usuarios", donde una de las columnas contiene una ID (no única, que identifica al usuario) (columna 10). la longitud del marco de datos es de aproximadamente 750000 filas. Estoy tratando de extraer marcos de datos individuales (para obtener una lista o vector de marcos de datos) divididos por la columna que contiene el identificador de "usuario", para aislar las acciones de un solo actor.
ID | Data1 | Data2 | ... | UserID
1 | aaa | bbb | ... | u_001
2 | aab | bb2 | ... | u_001
3 | aac | bb3 | ... | u_001
4 | aad | bb4 | ... | u_002
resultando en
list(
ID | Data1 | Data2 | ... | UserID
1 | aaa | bbb | ... | u_001
2 | aab | bb2 | ... | u_001
3 | aac | bb3 | ... | u_001
,
4 | aad | bb4 | ... | u_002
...)
Lo siguiente me funciona muy bien en una pequeña muestra (1000 filas):
paths = by(smallsampleMat, smallsampleMat[,"userID"], function(x) x)
y luego accediendo al elemento que quiero por rutas [1] por ejemplo.
Al aplicar en el marco de datos grande original o incluso una representación de matriz, esto ahoga mi máquina (4 GB de RAM, MacOSX 10.6, R 2.15) y nunca termina (sé que existe una versión R más nueva, pero creo que este no es el problema principal )
Parece que la división es más eficaz y después de un largo tiempo se completa, pero no sé (conocimiento R inferior) cómo dividir la lista resultante de vectores en un vector de matrices.
path = split(smallsampleMat, smallsampleMat[,10])
También he considerado usar big.matrix
, etc., pero sin mucho éxito eso aceleraría el proceso.
Puede acceder fácilmente a cada elemento de la lista usando, por ejemplo, la path[[1]]
. No se puede poner un conjunto de matrices en un vector atómico y acceder a cada elemento. Una matriz es un vector atómico con atributos de dimensión. Usaría la estructura de lista devuelta por split
, para lo que fue diseñada. Cada elemento de la lista puede contener datos de diferentes tipos y tamaños, por lo que es muy versátil y puede usar *apply
funciones de *apply
para seguir operando en cada elemento de la lista. Ejemplo a continuación.
# For reproducibile data
set.seed(1)
# Make some data
userid <- rep(1:2,times=4)
data1 <- replicate(8 , paste( sample(letters , 3 ) , collapse = "" ) )
data2 <- sample(10,8)
df <- data.frame( userid , data1 , data2 )
# Split on userid
out <- split( df , f = df$userid )
#$`1`
# userid data1 data2
#1 1 gjn 3
#3 1 yqp 1
#5 1 rjs 6
#7 1 jtw 5
#$`2`
# userid data1 data2
#2 2 xfv 4
#4 2 bfe 10
#6 2 mrx 2
#8 2 fqd 9
Acceda a cada elemento usando el operador [[
como este:
out[[1]]
# userid data1 data2
#1 1 gjn 3
#3 1 yqp 1
#5 1 rjs 6
#7 1 jtw 5
O use una función *apply
para realizar más operaciones en cada elemento de la lista. Por ejemplo, para tomar la media de la columna de data2
, puede usar Sapply de esta manera:
sapply( out , function(x) mean( x$data2 ) )
# 1 2
#3.75 6.25
Tropecé con esta respuesta y realmente quería AMBOS grupos (datos que contienen ese usuario y datos que contienen todo menos un usuario). No es necesario para los detalles de esta publicación, pero pensé que agregaría en caso de que alguien estuviera buscando en Google el mismo problema que yo.
df <- data.frame(
ran_data1=rnorm(125),
ran_data2=rnorm(125),
g=rep(factor(LETTERS[1:5]), 25)
)
test_x = split(df,df$g)[[''A'']]
test_y = split(df,df$g!=''A'')[[''TRUE'']]
head(test_x)
x y g
1 1.1362198 1.2969541 A
6 0.5510307 -0.2512449 A
11 0.0321679 0.2358821 A
16 0.4734277 -1.2889081 A
21 -1.2686151 0.2524744 A
> head(test_y)
x y g
2 -2.23477293 1.1514810 B
3 -0.46958938 -1.7434205 C
4 0.07365603 0.1111419 D
5 -1.08758355 0.4727281 E
7 0.28448637 -1.5124336 B
8 1.24117504 0.4928257 C