स्तंभ में सामान्य मूल्य के आधार पर डेटा फ़्रेम की सूची में एक बड़ी डेटाफ़्रेम को विभाजित करें


86

मेरे पास 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] से उस तत्व तक पहुँचना चाहता हूँ।

मूल बड़े डेटा फ़्रेम या यहां तक ​​कि मैट्रिक्स प्रतिनिधित्व पर आवेदन करते समय, यह मेरी मशीन (4 जीबी रैम, मैकओएसएक्स 10.6, आर 2.15) को चोक करता है और कभी पूरा नहीं होता है (मुझे पता है कि एक नया आर संस्करण मौजूद है, लेकिन मेरा मानना ​​है कि यह मुख्य समस्या नहीं है )।

ऐसा लगता है कि विभाजन अधिक निष्पादित होता है और लंबे समय के बाद पूरा होता है, लेकिन मुझे नहीं पता (अवर आर ज्ञान) कैसे वैक्टर की परिणामी सूची को मैट्रिस के वेक्टर में विभाजित किया जाए।

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

मैंने भी big.matrixआदि का उपयोग करने पर विचार किया है , लेकिन बहुत अधिक सफलता के बिना जो इस प्रक्रिया को गति देगा।

जवाबों:


103

आप बस उदाहरण के रूप में आसानी से सूची में प्रत्येक तत्व का उपयोग कर सकते हैं 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( out , function(x) mean( x$data2 ) )
#   1    2 
#3.75 6.25 

2
मैं प्रदर्शन के बारे में सोच रहा था dlply(df, .(userid))और पाया कि यह splitदौड़ के समय को शामिल किए बिना भी बुरा है require(plyr), धन्यवाद और ओपी!
फ्रांसिस

18

संस्करण 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)

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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.