J'ai un cadre de données avec 10 colonnes, rassemblant les actions des "utilisateurs", où l'une des colonnes contient un ID (non unique, identifiant utilisateur) (colonne 10). la longueur du cadre de données est d'environ 750000 lignes. J'essaie d'extraire des trames de données individuelles (afin d'obtenir une liste ou un vecteur de trames de données) divisées par la colonne contenant l'identifiant "utilisateur", afin d'isoler les actions d'un seul acteur.
ID | Data1 | Data2 | ... | UserID
1 | aaa | bbb | ... | u_001
2 | aab | bb2 | ... | u_001
3 | aac | bb3 | ... | u_001
4 | aad | bb4 | ... | u_002
résultant 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
...)
Ce qui suit fonctionne très bien pour moi sur un petit échantillon (1000 lignes):
paths = by(smallsampleMat, smallsampleMat[,"userID"], function(x) x)
puis en accédant à l'élément que je veux par des chemins [1] par exemple.
Lorsque j'applique sur le cadre de données volumineux d'origine ou même sur une représentation matricielle, ma machine (4 Go de RAM, MacOSX 10.6, R 2.15) s'étouffe et ne termine jamais (je sais qu'une version R plus récente existe, mais je pense que ce n'est pas le principal problème ).
Il semble que la scission soit plus performante et se termine après une longue période, mais je ne sais pas (connaissance de R inférieur) comment découper la liste de vecteurs résultante en un vecteur de matrices.
path = split(smallsampleMat, smallsampleMat[,10])
J'ai aussi envisagé d'utiliser big.matrix
etc., mais sans grand succès, cela accélérerait le processus.
Vous pouvez tout aussi facilement accéder à chaque élément de la liste en utilisant, par exemple, path[[1]]
. Vous ne pouvez pas mettre un ensemble de matrices dans un vecteur atomique et accéder à chaque élément. Une matrice est un vecteur atomique avec des attributs de dimension. J'utiliserais la structure de liste renvoyée par split
, c'est pour cela qu'elle a été conçue. Chaque élément de la liste peut contenir des données de types et de tailles différents, ce qui le rend très polyvalent et vous permet d’utiliser *apply
fonctions permettant d’agir sur chaque élément de la liste. Exemple ci-dessous.
# 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
Accédez à chaque élément en utilisant le [[
opérateur comme ceci:
out[[1]]
# userid data1 data2
#1 1 gjn 3
#3 1 yqp 1
#5 1 rjs 6
#7 1 jtw 5
Ou utilisez un *apply
fonction pour effectuer des opérations supplémentaires sur chaque élément de la liste. Par exemple, prenons la moyenne du data2
la colonne que vous pourriez utiliser comme ceci:
sapply( out , function(x) mean( x$data2 ) )
# 1 2
#3.75 6.25
Je suis tombé par hasard sur cette réponse et je voulais à la fois DEUX groupes (des données contenant cet utilisateur et des données contenant tout sauf cet utilisateur). Pas nécessaire pour les détails de ce post, mais je pensais ajouter si quelqu'un cherchait sur Google le même problème que moi.
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']]
Voici à quoi ça ressemble:
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
Depuis la version 0.8.0, dplyr
offre une fonction pratique appelée group_split()
:
# On sample data from @Aus_10
df %>%
group_split(g)
[[1]]
# A tibble: 25 x 3
ran_data1 ran_data2 g
<dbl> <dbl> <fct>
1 2.04 0.627 A
2 0.530 -0.703 A
3 -0.475 0.541 A
4 1.20 -0.565 A
5 -0.380 -0.126 A
6 1.25 -1.69 A
7 -0.153 -1.02 A
8 1.52 -0.520 A
9 0.905 -0.976 A
10 0.517 -0.535 A
# … with 15 more rows
[[2]]
# A tibble: 25 x 3
ran_data1 ran_data2 g
<dbl> <dbl> <fct>
1 1.61 0.858 B
2 1.05 -1.25 B
3 -0.440 -0.506 B
4 -1.17 1.81 B
5 1.47 -1.60 B
6 -0.682 -0.726 B
7 -2.21 0.282 B
8 -0.499 0.591 B
9 0.711 -1.21 B
10 0.705 0.960 B
# … with 15 more rows
Pour ne pas inclure la colonne de regroupement:
df %>%
group_split(g, keep = FALSE)