【问题标题】:Getting the top n values by group not working as expected按组获取前 n 个值未按预期工作
【发布时间】:2019-04-24 20:29:18
【问题描述】:

考虑以下数据帧的 head(10):

它是由这个 dplyr 代码生成的:

Fuller_list %>% 
 as.data.frame() %>% 
 select(from_infomap, topic) %>%
 add_count(from_infomap) %>% 
 filter(from_infomap %in% coms_keep) %>% 
 group_by(from_infomap) %>%
 add_count(topic) %>%
 top_n(10, nn) %>%
 head(10)

“from_infomap”栏中有 36 个不同的社区,“topic”栏中有 47 个不同的主题。按“from_infomap”分组每个社区的主题数量,对于前 5 个社区,如下所示:

我想展示每个社区最常见的 10 个主题,按降序排列。我在这里尝试这样做:

 group_by(from_infomap) %>%
 add_count(topic) %>%
 top_n(10, nn) 

但如果我绘制它,它只会返回每个社区的前 1 个主题:

我不确定我做错了什么。根据this 堆栈溢出查询,计数上的加权 top_n(n,wt) 函数应该可以工作,它应该给出按计数加权的前 10 个主题,按社区分组。

如果有人可以提出替代方案或指出我哪里出错了,将不胜感激。对于小屏幕截图,我无法在此处显示整个 data.frame,因为它非常大。

谢谢!

编辑:没有 group_by、add_count 和 top_n 的 dput:

n <- Fuller_list %>% 
 as.data.frame() %>% 
 select(from_infomap, topic) %>%
 add_count(from_infomap) %>% 
 filter(from_infomap %in% coms_keep) %>% 
 group_by(from_infomap)

输入(头(n,10)):

structure(list(from_infomap = c(1L, 1L, 1L, 3L, 3L, 3L, 4L, 4L, 
4L, 4L), topic = c("KnysnaFire_thanks_wofire", "Abramjee_caperelief_operationsa", 
"Pick_n_Pay", "Plett_heavy_rain_snow", "Disasters_help_call", 
"KFM_disasters_discussion", "Pick_n_Pay", "Pick_n_Pay", "Pick_n_Pay", 
"Pick_n_Pay"), n = c(30512L, 30512L, 30512L, 6572L, 6572L, 6572L, 
5030L, 5030L, 5030L, 5030L)), row.names = c(NA, -10L), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"), vars = "from_infomap", drop = TRUE, indices = list(
    0:2, 3:5, 6:9), group_sizes = c(3L, 3L, 4L), biggest_group_size = 4L, labels = structure(list(
    from_infomap = c(1L, 3L, 4L)), row.names = c(NA, -3L), class = "data.frame", vars = "from_infomap", drop = TRUE))

通过将此代码添加到前一个块应该可以重现问题:

  add_count(topic) %>%
  top_n(10,nn) %>%
  ungroup() %>% 
  ggplot(aes(x = fct_reorder(topic,nn),y = nn,fill = from_infomap))+
  geom_col(width = 1)+
  facet_wrap(~from_infomap, scales = "free")+
  coord_flip()+
  theme(plot.title = element_text("Central Players"), 
        plot.subtitle= element_text("Top 10 indegree centrality profiles of the 20 biggest communities.\n Excluding 'starburst' communities."),
        plot.caption = element_text("Source: Twitter"))+
  theme_few()

Halway-Solution:所以使用@s_t 建议的summary 方法,我们有以下代码:

Fuller_list %>% 
  as.data.frame() %>% 
  add_count(from_infomap) %>%
  filter(from_infomap %in% coms_keep) %>% 
  group_by(from_infomap,topic) %>%   # group by the topic and community
  summarise(nn = n()) %>%            # count the mentioned arguments
  top_n(10, nn) %>%
  ungroup() %>%
  arrange(from_infomap, nn) %>%
  ggplot(aes(x = fct_reorder(topic,nn),y = nn,fill = from_infomap))+
  geom_col(width = 1)+
  facet_wrap(~from_infomap, scales = "free")+
  coord_flip()+
  theme(plot.title = element_text("Central Players"), 
        plot.subtitle= element_text("Top 10 indegree centrality profiles of the 20 biggest communities.\n Excluding 'starburst' communities."),
        plot.caption = element_text("Source: Twitter"))+
  theme_few()

这会产生:

哪个是各个社区中正确的top_n(10)。出于所有实际目的,该图现在显示了正确的数据。唯一剩下的问题是,排列不是按 每个社区 的 desc 顺序对各种主题进行排序,而是按整体排序。小问题,如果主题可以按社区安排,只会改善 aes。

【问题讨论】:

  • 你能发布一些有用的数据(不是图片)吗?
  • 这里有一些提示:stackoverflow.com/questions/5963269/…
  • @s_t 我添加了指向可下载代码示例的链接。我希望这就是你要找的东西? drive.google.com/file/d/128R9Vgjd2QsFwHf0M5Yi8ltli2dsDsrJ/…
  • @snoram,我想使用 dput 来提供代码示例,但是数据集非常大(很多变量),在这里实际上无法查看。我提供了一个 1000 行示例的链接,我希望这是为了?
  • @s_t 当然,我在下面添加了 dput(head()) 的输出。那是你要找的吗?抱歉,我还没有这方面的经验。

标签: r dataframe dplyr


【解决方案1】:

也许这会有所帮助,如果我理解得很好,您想计算每个社区中的主题,选择顶部(X),并在每个方面以递减的方式绘制它们:

library(ggplot2)
library(dplyr)

data3 <-
  data2 %>%
  select(-n) %>%                     # remove useless column
  group_by(from_infomap,topic) %>%   # group by the topic and community
  summarise(nn = n()) %>%            # count the mentioned arguments
  top_n(5, nn)                       # take the top 5 in this case

现在我们处理订单,如here所述:

data4 <- data3 %>% 
         ungroup() %>%  
         arrange(from_infomap, nn) %>%  
         mutate(topic_r = row_number()) 

最后是剧情:

ggplot(data4, aes(topic_r, nn,fill = from_infomap)) + 
geom_col() +
facet_wrap(~ from_infomap, scales = "free") +
scale_x_continuous(  
                   breaks = d$topic_r,  
                   labels = d$topic
                  ) +
coord_flip()

我使用了一些虚假数据,例如:

data2 <- data.frame(from_infomap =floor(runif(200, 1,5)) ,
                    topic = sample(letters[1:20], 200, TRUE),
                    n = floor(runif(200, 10,50)) )

社区中的许多主题都有相同的编号,所以您不会只看到 5 列。

【讨论】:

  • 这绝对是朝着正确方向迈出的一步,我现在每个社区都有多个主题。不过,我只是为每一行绘制了一个图,但我将处理这个问题并给你一个解决方案。非常感谢您的努力!
  • 如果您删除了问题广告中无用的部分,请使用此答案更新它,如果还有其他问题,我们可以尝试解决所有问题。
  • 我在问题中添加了一个“中途解决方案”并添加了您的代码。唯一剩下的问题是整体应用的安排,而不是每个社区。但是,我很高兴已经在绘图上正确表示了数据。非常感谢!
  • 查看您的新代码,您忘记了我的 data4 的一些步骤,例如 mutate(...) 添加要在图中使用的变量,以及 scale_x_continuous(...) 部分在图中,订购酒吧。
  • 我尝试将 topic_r 的 mutate() 和 scale_x_continuous 添加到绘图中,但出现错误:将离散值提供给连续比例。我尝试了几种解决方案,例如 scale_x_discrete,或者按照另一个 stackoverflow 问题的建议将 topic_r 强制转换为数值,但没有成功。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多