为何filter()函数位置不同会生成不同直方图?附对比代码
为什么这两段代码生成的直方图不同?
这是个非常典型的dplyr分组操作误区——核心问题在于**filter(n() >= 100) 在代码中所处的位置,决定了它作用的对象完全不一样**,咱们拆解来看:
第一段代码的执行逻辑
library(tidyverse) library(dslabs) movielens %>% group_by(userId) %>% filter(n() >= 100) %>% summarise(mean_rating = mean(rating)) %>% ggplot(aes(mean_rating)) + geom_histogram(bins=30, col="black")
- 第一步按
userId分组,此时每个组对应一个用户的所有评分记录 filter(n() >= 100)在这里的n()指的是每个用户的评分条数——这一步直接把那些评分少于100条的用户组全部过滤掉了,只保留至少打了100分的用户数据- 接下来对剩下的每个用户组计算平均评分,最后用这些“活跃用户”的平均评分绘制直方图
第二段代码的执行逻辑
movielens %>% group_by(userId) %>% summarise(mean_rating = mean(rating)) %>% filter(n() >= 100) %>% ggplot(aes(mean_rating)) + geom_histogram(bins=30, col="black")
这里的坑就在filter的位置:
- 同样先按
userId分组,然后直接对所有用户(不管评分多少)计算了平均评分 - 关键!
summarise函数默认会在执行后自动取消分组(相当于调用了ungroup()),所以此时整个数据框已经回到了未分组状态,每行对应一个用户的平均评分 - 这时调用
filter(n() >= 100),这里的n()指的是整个数据框的总行数(也就是用户总数),而movielens的用户数远大于100,所以这个过滤条件等于完全没起作用——最终你是用所有用户的平均评分绘制了直方图
总结
第一段是“先筛选出评分≥100的用户,再统计他们的平均评分分布”;第二段是“先统计所有用户的平均评分,然后做了一个无效过滤,最终统计所有用户的平均评分分布”。两者的数据源不同,直方图自然就不一样了。
内容的提问来源于stack exchange,提问作者Ryan Ma
相关产品推荐
相关产品推荐

