2013-08-30 13 views
44

Mam ramkę danych z 10 kolumnami, zbierającą akcje "użytkowników", gdzie jedna z kolumn zawiera identyfikator (nie jest to unikalny, identyfikujący użytkownika) (kolumna 10). długość ramki danych wynosi około 750000 wierszy. Próbuję wyodrębnić pojedynczych ramek danych (więc uzyskanie listy lub wektor ramek danych) podzielone przez kolumnę zawierającą identyfikator "użytkownika", aby wyizolować działania pojedynczego aktora.Podziel dużą ramkę danych na listę ramek danych na podstawie wspólnej wartości w kolumnie

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

prowadzące do

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

następujące prace bardzo dobrze dla mnie na małej próbce (1000 wierszy):

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

a następnie dostęp do 1 elementu chcę ścieżkami [ ] na przykład.

Podczas nakładania na oryginalną dużą ramkę danych lub nawet na matrycę, dławi mój komputer (4 GB RAM, MacOSX 10.6, R 2.15) i nigdy się nie kończy (wiem, że istnieje nowsza wersja R, ale uważam, że to jest nie główny problem).

Wygląda na to, że podział jest bardziej wydajny i po długim czasie się kończy, ale nie wiem (gorsza wiedza R), jak podzielić wynikową listę wektorów na wektor macierzy.

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

Mam również uważane za pomocą big.matrix itp, ale bez większych sukcesów, które przyspieszają ten proces.

Odpowiedz

50

Możesz równie łatwo uzyskać dostęp do każdego elementu na liście za pomocą np. path[[1]]. Nie można umieścić zestawu macierzy w wektorze atomowym i uzyskać dostępu do każdego elementu. Macierz jest wektorem atomowym z atrybutami wymiarów. Chciałbym użyć struktury listy zwróconej przez split, do której został zaprojektowany. Każdy element listy może przechowywać dane różnych typów i rozmiarów, więc jest bardzo wszechstronny i można używać funkcji *apply do dalszego działania na każdym elemencie na liście. Przykład poniżej.

# 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 

dostęp każdy element za pomocą operatora [[ tak:

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

Albo użyć funkcji *apply robić dalsze operacje na każdego elementu listy. Na przykład, aby wziąć średnią z kolumny data2 można użyć sapply tak:

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

Zastanawiałem wydajność 'dlply (DF,.(userid)) 'i stwierdził, że jest zły w porównaniu do' split' nawet bez angażowania czasu wykonywania 'require (plyr)', dziękuję i OP! – Francis

3

natknęliśmy się na to odpowiedź, a ja właściwie chciałem obu grupach (dane zawierające że jeden użytkownik i danych zawierająca wszystko, ale jednego użytkownika) . Nie jest to konieczne ze względu na specyfikę tego posta, ale pomyślałem, że dodam na wypadek, gdyby ktoś szukał tego samego problemu co ja.

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']]
Oto jak to wygląda:

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

Powiązane problemy