2013-08-30 64 views
44

Tôi có một khung dữ liệu với 10 cột, thu thập hành động của "người dùng", trong đó một trong các cột chứa ID (không phải là duy nhất, nhận dạng người dùng) (cột 10). chiều dài của khung dữ liệu là khoảng 750000 hàng. Tôi đang cố gắng trích xuất các khung dữ liệu riêng lẻ (để lấy danh sách hoặc vectơ của các khung dữ liệu) chia cho cột chứa mã định danh "người dùng", để cô lập các hành động của một tác nhân đơn lẻ.Tách một khung dữ liệu lớn thành một danh sách các khung dữ liệu dựa trên giá trị chung trong cột

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

kết quả vào

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

Các công trình sau đây rất tốt cho tôi trên một mẫu nhỏ (1000 dòng):

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

và sau đó truy cập vào các yếu tố tôi muốn bằng đường dẫn [1 ] ví dụ.

Khi áp dụng trên khung dữ liệu lớn ban đầu hoặc thậm chí là biểu diễn ma trận, điều này sẽ tắt máy của tôi (RAM 4GB, MacOSX 10.6, R 2.15) và không bao giờ hoàn thành (tôi biết rằng phiên bản R mới hơn tồn tại, nhưng tôi tin rằng đây là không phải là vấn đề chính). Có vẻ như việc chia nhỏ có hiệu suất cao hơn và sau một thời gian dài hoàn thành, nhưng tôi không biết (kiến thức R kém) làm thế nào để chia danh sách kết quả của vectơ thành một vec-tơ ma trận.

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

Tôi cũng đã xem xét sử dụng big.matrix v.v. nhưng không thành công nhiều, điều đó sẽ đẩy nhanh quá trình.

Trả lời

50

Bạn có thể dễ dàng truy cập từng phần tử trong danh sách bằng cách sử dụng ví dụ: path[[1]]. Bạn không thể đặt một bộ ma trận vào một vector nguyên tử và truy cập từng phần tử. Ma trận là một vector nguyên tử có thuộc tính thứ nguyên. Tôi sẽ sử dụng cấu trúc danh sách được trả về bởi split, đó là cấu trúc được thiết kế cho nó. Mỗi phần tử danh sách có thể chứa dữ liệu của các loại và kích cỡ khác nhau, vì vậy nó rất linh hoạt và bạn có thể sử dụng các hàm *apply để tiếp tục hoạt động trên từng phần tử trong danh sách. Ví dụ bên dưới.

# 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 

truy cập mỗi phần tử sử dụng toán tử [[ như thế này:

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

Hoặc sử dụng một chức năng *apply làm với thaco tác hơn nữa trên mỗi phần tử trong danh sách. Ví dụ, để lấy giá trị trung bình của cột data2 bạn có thể sử dụng sapply như thế này:

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

tôi đã tự hỏi hiệu suất của 'dlply (df,.(userid)) 'và thấy rằng nó là xấu so với' split' thậm chí không liên quan đến thời gian chạy của 'require (plyr)', cảm ơn bạn và OP! – Francis

3

Tình cờ gặp câu trả lời này và tôi thực sự muốn cả hai nhóm (dữ liệu có chứa một người dùng và dữ liệu chứa tất cả mọi thứ nhưng điều đó một người dùng) . Không cần thiết cho các chi tiết cụ thể của bài đăng này, nhưng tôi nghĩ tôi sẽ thêm vào trong trường hợp ai đó đang gặp vấn đề tương tự như tôi.

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']]
Đây là những gì nó trông giống như:

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

Các vấn đề liên quan