通过堆积条形图中的数字变量对具有分类变量的列进行排序

时间:2019-04-09 10:31:48

标签: r ggplot2

我有一个包含数字(百分比)和分类变量的数据框。我想生成一个堆积的条形图(使用ggplot2),并用数值变量对列(类别变量)进行排序。

我尝试过:

How to control ordering of stacked bar chart using identity on ggplot2

还有:

https://community.rstudio.com/t/a-tidy-way-to-order-stacked-bar-chart-by-fill-subset/5134

但是我不熟悉因素,我想了解更多。

# Reproduce a dummy dataset
perc <- c(11.89, 88.11, 2.56, 97.44, 5.96, 94.04, 6.74, 93.26)
names <- c('A', 'A', 'B', 'B', 'C', 'C', 'D', 'D')

df <- data.frame(class = rep(c(-1, 1), 4), 
                 percentage = perc, 
                 name = names)

# Plot
ggplot(df, aes(x = factor(name), y = percentage, fill = factor(class))) +
  geom_bar(stat = "identity") +
  scale_fill_discrete(name = "Class") +
  xlab('Names')

此代码生成一个图,其条形由变量“名称”排序。我想按变量“百分比”对其进行排序。即使我手动订购数据框,结果图也一样。

3 个答案:

答案 0 :(得分:1)

这里的问题是,给定类别(name)的所有百分比实际上合计为100%。因此,按百分比排序(通常通过aes(x = reorder(name, percentage), y = percentage)实现)在这里不起作用。

相反,您可能想按具有class = 1(或class = -1)的数据的百分比排序。这样做需要一些技巧:使用ifelseclass == 1中的行选择百分比。对于所有其他行,选择值0:

ggplot(df, aes(x = reorder(name, ifelse(class == 1, percentage, 0)), y = percentage, fill = factor(class))) +
  geom_bar(stat = "identity") +
  scale_fill_discrete(name = "Class") +
  xlab('Names')

您可能只想执行reorder指令以查看发生的情况:

reorder(df$name, ifelse(df$class == 1, df$percentage, 0))
# [1] A A B B C C D D
# attr(,"scores")
#      A      B      C      D
# 44.055 48.720 47.020 46.630
# Levels: A D C B

如您所见,您的姓名根据每个类别的平均百分比重新排序(默认情况下,reorder使用均值; see its manual page for more details)。但是我们计算出的“均值”介于类别= 1的每个名称的百分比与值0(类别≠1的值)之间。

答案 1 :(得分:0)

它与Konrad Rudolph类似,我刚刚创建了一个因子水平,并使用它进行重新排序。这是我的解决方案:

x_order <- with(subset(df, class == -1), reorder(name, percentage))
df$name <- factor(df$name, levels = levels(x_order))
ggplot(df, aes(x = name,  y = percentage, fill = factor(class))) +
  geom_bar(stat = "identity") +
  scale_x_discrete(breaks = levels(x_order))

答案 2 :(得分:0)

在绘制之前更改水平会为您完成

  

lvlorder = order((df [df $ class ==-1,])$百分比,递减= T)

     

df $ name = factor(df $ name,level = level(df $ name)[lvlorder])