【问题标题】:Is there a way to reorder the level of a variable after grouping using group_by?有没有办法在使用 group_by 分组后重新排序变量的级别?
【发布时间】:2018-09-25 01:45:47
【问题描述】:

我正在尝试重现“使用 R 进行文本挖掘”一书第 4.1.3 节中的图 4.3。 sentiment analysis

本部分试图通过四个关键否定词“not”、“no”、“never”和“without”对所有二元组进行分组,并且对于每个组,它将绘制情绪贡献(仅由否定词,表示错误的贡献)对本书的贡献。

所以我会将单词绘制为 y 轴,将贡献绘制为 x 轴,为了使图表看起来不错,我还希望每个组的条形按降序排列。因此,与前几节类似,我使用贡献值重新排序单词的级别。

但这里的问题是,在每个组下,这些词会有不同的贡献。例如在第 1 组中,“快乐”比“希望”出现的次数更多,因此贡献更高,但在第 2 组中,则相反。更糟糕的是,当数据框为group_by(word1) 时,我无法执行mutate(word2 = reorder(word2, contribution))

这本书能够很好地产生应有的情节,所以我想有一些方法可以根据不同的群体重新排序。

下面是代码,#preparing the data for plotting 之前的任何内容都取自本书,所以应该没有任何问题,从那里代码是我的。

library(dplyr)
library(tidytext)
library(janeaustenr)
library(tidyr)

#getting bigrams

austen_bigrams <- austen_books() %>%
  unnest_tokens(bigram, text, token = "ngrams", n = 2)  
bigrams_separated <- austen_bigrams %>%
  separate(bigram, c("word1", "word2"), sep = " ")  

#four negation words to look at

negation_words <- c("not", "no", "never", "without")
AFINN <- get_sentiments("afinn")

#get the sentiment score of words preceded by the four negation words

negated_words <- bigrams_separated %>%
  filter(word1 %in% negation_words) %>%  #word1 as negation words
  inner_join(AFINN, by = c(word2 = "word")) %>%  #word2 as the word following negation words
  count(word1, word2, score, sort = TRUE) %>%
  ungroup()

#preparing the data for plotting

bigrams_plot <- bigrams_separated %>%
  filter(word1 %in% negation_words) %>% 
  inner_join(AFINN, by = c(word2 = "word")) %>%  #getting sentiment score
  count(word1, word2, score, sort = TRUE) %>%
  mutate(contribution = n * score) %>%  #defining contribution as n*score
  group_by(word1) %>%  #group by negation words
  top_n(12,abs(contribution)) %>%
  arrange(desc(abs(contribution))) %>%
  ungroup() %>%
  mutate(word2 = reorder(word2, contribution)) 

#plotting sentiment score contribution grouped by the four negation words

ggplot(bigrams_plot, aes(word2, n * score, fill = n * score > 0)) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~word1, ncol = 2, scales = "free") +
  coord_flip()

我在下面创建了一个更简单的版本:

v1_grp <- c(rep('A',10),rep('B',10))
v2_Aterm <- sample(letters[1:10],10,replace=F)
v2_Bterm <- sample(letters[1:10],10,replace=F)
v3_score <- sample(-10:10,20,replace=T)

data1 <- data_frame(grp=v1_grp,term=c(v2_Aterm,v2_Bterm),score=v3_score)

dataplot <- data1 %>%
  arrange(desc(score)) %>%
  mutate(term=reorder(term,score)) 

ggplot(dataplot, aes(term,score,fill=score>0)) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~grp, ncol = 2, scales = "free") +
  coord_flip()

【问题讨论】:

  • 这样做的方法是创建一个新列,将 y 轴项和 facet 项与paste 组合在一起,然后您可以重新排序并将其放在 y 轴上(使用 @ 987654330@),但使用原始列中的相应值作为轴标签。
  • 如果您创建一个更简单的示例(例如,
  • @Gregor 感谢您的建议,我在下面添加了一个更简单的版本。

标签: r dplyr


【解决方案1】:

(改编自https://drsimonj.svbtle.com/ordering-categories-within-ggplot2-facets

dataplot <- data1 %>%
  arrange(grp, score) %>%
  mutate(order = row_number())

ggplot(dataplot, aes(order,score,fill=score>0)) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~grp, ncol = 2, scales = "free") +
  coord_flip() +
  scale_x_continuous(
    breaks = dataplot$order,
    labels = dataplot$term,
    expand = c(0,0)
  )

【讨论】:

  • 只是一个小问题,如果不同的组没有太多共同的术语,情节中会出现很多空条,有没有办法避免这种情况?
  • 不确定我是否理解。上面答案中的空条是分数为零的地方。如果我们将样本数据切换到v2_Aterm &lt;- sample(letters[1:26],10,replace=F); v2_Bterm &lt;- sample(letters[1:26],10,replace=F); v3_score &lt;- runif(20,-10, 10),它似乎仍然有效,这使得组的共同行更少,并减少大多数零分。
  • 啊,我明白了,设法整理出来,我之前可能有部分代码错误。谢谢。
猜你喜欢
  • 1970-01-01
  • 2020-02-26
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2018-09-01
  • 2021-09-30
  • 1970-01-01
相关资源
最近更新 更多