열의 공통 값을 기반으로 큰 데이터 프레임을 데이터 프레임 목록으로 분할


88

열 중 하나에 ID (고유하지 않은 사용자 식별) (10 열)가 포함 된 "사용자"의 작업을 수집하는 10 개의 열이있는 데이터 프레임이 있습니다. 데이터 프레임의 길이는 약 750000 행입니다. 단일 액터의 동작을 분리하기 위해 "사용자"식별자를 포함하는 열로 분할 된 개별 데이터 프레임 (데이터 프레임의 목록 또는 벡터 가져 오기)을 추출하려고합니다.

ID | Data1 | Data2 | ... | UserID
1  | aaa   | bbb   | ... | u_001
2  | aab   | bb2   | ... | u_001
3  | aac   | bb3   | ... | u_001
4  | aad   | bb4   | ... | u_002

결과로

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
...)

다음은 작은 샘플 (1000 행)에서 매우 잘 작동합니다.

paths = by(smallsampleMat, smallsampleMat[,"userID"], function(x) x)

예를 들어 경로 [1]로 원하는 요소에 액세스합니다.

원래의 대용량 데이터 프레임이나 심지어 행렬 표현에 적용 할 때, 이것은 내 컴퓨터 (4GB RAM, MacOSX 10.6, R 2.15)를 질식시키고 완료되지 않습니다 (새로운 R 버전이 존재한다는 것을 알고 있지만 이것이 주요 문제는 아니라고 생각합니다. ).

분할이 더 성능이 뛰어나고 오랜 시간이 지난 후에 완료되는 것처럼 보이지만 결과 벡터 목록을 행렬 벡터로 조각하는 방법을 알지 못합니다 (열등한 R 지식).

path = split(smallsampleMat, smallsampleMat[,10]) 

나는 big.matrix등 을 사용하는 것을 고려 했지만 많은 성공이 없으면 프로세스 속도가 빨라집니다.

답변:


104

예를 사용하여 목록의 각 요소에 쉽게 액세스 할 수 있습니다 path[[1]]. 원자 벡터에 행렬 집합을 넣고 각 요소에 액세스 할 수 없습니다. 행렬은 차원 속성이있는 원자 벡터입니다. 에서 반환 된 목록 구조를 사용합니다 split. 각 목록 요소는 다양한 유형과 크기의 데이터를 보유 할 수 있으므로 매우 다양하며 *apply함수를 사용 하여 목록의 각 요소에 대해 추가로 작업 할 수 있습니다 . 아래 예.

#  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

다음 [[과 같은 연산자를 사용하여 각 요소에 액세스 합니다.

out[[1]]
#  userid data1 data2
#1      1   gjn     3
#3      1   yqp     1
#5      1   rjs     6
#7      1   jtw     5

또는 *apply함수를 사용하여 각 목록 요소에 대해 추가 작업을 수행합니다. 예를 들어, data2열의 평균을 취 하려면 다음과 같이 sapply를 사용할 수 있습니다.

sapply( out , function(x) mean( x$data2 ) )
#   1    2 
#3.75 6.25 

2
의 성능이 궁금해서 , OP 의 런타임을 포함하지 않아도 dlply(df, .(userid))비교가 나쁘다는 것을 알았습니다 ! splitrequire(plyr)
Francis

21

버전 0.8.0부터 dplyr다음 과 같은 편리한 기능을 제공합니다 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

그룹화 열을 포함하지 않으려면 :

df %>%
 group_split(g, keep = FALSE)

삭제 된 그룹화 열을 사용하여 목록의 이름을 지정하는 방법이 있습니까? 나는 이것을 할 수 있다는 것을 알고있다 : 그러나 dplyr? names (f.vars.h1.list) <-unique (f.vars.to.agg.1h $ ActivityGroup)
d3hero23

9

이 답변을 우연히 발견하고 실제로 두 그룹 모두를 원했습니다 (한 사용자를 포함하는 데이터와 해당 사용자를 제외한 모든 것을 포함하는 데이터). 이 게시물의 세부 사항에는 필요하지 않지만 누군가 나와 같은 문제를 검색하는 경우 추가 할 것이라고 생각했습니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.