我有一个包含一百万条记录的数据集,我需要在首次对数据进行子集后进行聚合。很难提供良好的可重复样本,因为在这种情况下,样本量会相当大 - 但无论如何我都会尝试。
我正在使用的数据的随机样本如下所示:
> 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
正如我们所看到的,在完整的数据集中,在7月份(月份= 7),用户已经多次旅行。现在重要的部分 - 仅对这些用户的前10%进行子集(Freq
方面排名前10%)
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 ...
有没有办法使用dplyr
自动执行此过程 - 我的意思是前十分之一的子集?我试过了
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)
答案 0 :(得分:1)
下面的代码计算每个user_id
中每个month
的行数,然后选择每个月中行数最多的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))
更新:跟进您的评论,让我们检查一些虚假数据。下面我们有30个不同的user_id
值和10,000个总行数。我还使用了prob
参数,以便选择user_id
的概率与其值成比例(即,user_id
1是最不可能被选择的user_id
{ {1}} 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_id
的每个month==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%的用户。要回答评论中的问题,filter(percent_rank(n) >= 0.9)
仅保留user_id
的前10%,基于n
的值(每个user_id
的行数)。 percent_rank
中的dplyr
中的几个排名函数具有不同的处理关系的方式(这可能是您未获得预期结果的原因)。有关详细信息,请参阅?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
所以看起来代码完成了我们天真的期望,但问题可能与如何处理关系有关。如果您的实际数据仍然存在异常结果,或者我误解了您要完成的任务,请告诉我。