2017-03-05 54 views
0

我有一个数据集,其中有一百万条记录,我需要在第一个子集数据之后进行聚合。提供良好的可重复性样品很困难,因为在这种情况下,样品量会相当大 - 但我会尽量尝试。由dplyr中的子集聚合

,我跟长相这样工作了数据的随机样本:

> df 
     auto_id user_id month 
164537 7124 240249 10 
151635 7358 226423  9 
117288 7376 172463  9 
177119 6085 199194 11 
128904 7110 141608  9 
157194 7143 241964  9 
71303  6090 141646  7 
72480  6808 175910  7 
108705 6602 213098  8 
97889  7379 185516  8 
184906 6405 212580 12 
37242  6057 197905  8 
157284 6548 162928  9 
17910  6885 194180 10 
70660  7162 161827  7 
8593  7375 207061  8 
28712  6311 176373 10 
144194 7324 142715  9 
73106  7196 176153  7 
67065  7392 171039  7 
77954  7116 161489  7 
59842  7107 162637  7 
101819 5994 182973  9 
183546 6427 142029 12 
102881 6477 188129  8 

在每个月,有很多用户谁都是一样的,而且首先要按月子集,使频率表用户和取(不幸的是,所述随机样品中上面有每个用户只有一个行程,但在较大的数据集,这是的情况下)行程的量的:

full_data <- full_data[full_data$month == 7,] 
users <- as.data.frame(table(full_data$user_id)) 
head(users) 
    Var1 Freq 
1 100231 10 
2 100744 17 
3 111281 1 
4 111814 2 
5 113716 3 
6 117493 3 

正如我们可以请在完整的数据集中查看o月份f七月(月= 7),用户已经进行了多次旅行。现在重要的部分 - 这是子集只有这些用户的前10%(前10%的Freq方面)

tenPercent = round(nrow(users)/10) 
users <- users[order(-users$Freq),] 
topten <- head(users, n = tenPercent) 

现在,新的数据框 - topten - 可以总结,我们可以得到的金额用户

sum(topten$Freq) 
[1] 12147 

最终输出应该是这样的

> output 
    month trips 
1  7 12147 
2  8 ... 
3  9 ... 
4  10 ... 
5  11 ... 
6  12 ... 

的前10%采取车次是否有办法来自动使用这一过程- 我的意思是特别是前10%的子集?我已经尝试过

output <- full_data %>% 
+  group_by(month) %>% 
+  summarise(n = n()) 

但是,这只能按月累计总次数。有人可以建议一种方法将这部分集成到dplyr的查询中吗? :

tenPercent = round(nrow(users)/10) 
users <- users[order(-users$Freq),] 
topten <- head(users, n = tenPercent) 

回答

1

下面的代码计数行的在每个monthuser_id的数量,然后在每个月最行选择用户的10%,并对其求和。让我知道它是否可以解决您的问题。

library(dplyr) 

full_data %>% group_by(month, user_id) %>% 
    tally %>% 
    group_by(month) %>% 
    filter(percent_rank(n) >= 0.9) %>% 
    summarise(n_trips = sum(n)) 

UPDATE:您的评论跟进,让我们做一些假数据的检查。以下我们有user_id 30个不同的值和总共10,000行。我还使用了prob参数,以便选择user_id的概率与其值成比例(即,最可能选择user_id 1,并且最有可能选择user_id 30)。

set.seed(3) 
full_data = data.frame(user_id=sample(1:30,10000, replace=TRUE, prob=1:30), 
         month=sample(1:12, 10000, replace=TRUE)) 

让我们看看作为行的每个user_idmonth==1数。下面的代码计算每个user_id的行数,并且从最常见到最不常见。请注意,user_id(28,29,26)三个最常见的值包含171行(60 + 57 + 54)。由于是user_id 30个不同值的前三位用户代表用户的前10%:

full_data %>% filter(month==1) %>% 
    group_by(month, user_id) %>% 
    tally %>% 
    arrange(desc(n)) %>% as.data.frame 
month user_id n 
1  1  28 60 
2  1  29 57 
3  1  26 54 
4  1  30 53 
5  1  27 49 
6  1  22 43 
7  1  21 41 
8  1  20 40 
9  1  23 40 
10  1  24 38 
11  1  25 38 
12  1  19 37 
13  1  18 33 
14  1  16 28 
15  1  15 27 
16  1  17 27 
17  1  14 26 
18  1  9 20 
19  1  12 20 
20  1  13 20 
21  1  10 17 
22  1  11 17 
23  1  6 15 
24  1  7 13 
25  1  8 13 
26  1  4 9 
27  1  5 7 
28  1  2 3 
29  1  3 2 
30  1  1 1 

现在让我们采取下一个步骤,并选择用户的前10%。要回答您评论中的问题,根据n(这是每个user_id的行数)的值,filter(percent_rank(n) >= 0.9)仅保留user_id的前10%。 percent_rankdplyr中有几个排名函数,它们有不同的处理关系的方法(这可能是您没有得到预期结果的原因)。详情请参见?percent_rank

full_data %>% filter(month==1) %>% 
    group_by(month, user_id) %>% 
    tally %>% 
    group_by(month) %>% 
    filter(percent_rank(n) >= 0.9) 
month user_id  n 
1  1  26 54 
2  1  28 60 
3  1  29 57 

n(车次前10%的总人数)之和为:

full_data %>% filter(month==1) %>% 
    group_by(month, user_id) %>% 
    tally %>% 
    group_by(month) %>% 
    filter(percent_rank(n) >= 0.9) %>% 
    summarise(n_trips = sum(n)) 
month n_trips 
1  1  171 

所以它看起来像代码完成我们天真的期望,但也许这个问题与如何处理关系有关。让我知道你是否仍然在真实数据中得到异常结果,或者我误解了你想要完成的事情。

+0

谢谢你的尝试。答案有点偏离(大约1000次左右,比预期的要少),'filter(percent_rank(n)> = 0.9)'如何工作? –