简体   繁体   English

如何使用 ggplot2 上的标识控制堆积条形图的排序

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

Using this dummy data.frame使用这个虚拟data.frame

ts <- data.frame(x=1:3, y=c("blue", "white", "white"), z=c("one", "one", "two"))

I try and plot with category "blue" on top.我尝试在顶部绘制类别“蓝色”。

ggplot(ts, aes(z, x, fill=factor(y, levels=c("blue","white" )))) + geom_bar(stat = "identity")

在此处输入图片说明

gives me "white" on top.在上面给我“白色”。 and

ggplot(ts, aes(z, x, fill=factor(y, levels=c("white", "blue")))) + geom_bar(stat = "identity")

在此处输入图片说明

reverses the colors, but still gives me "white" on top.反转颜色,但仍然在顶部给我“白色”。 How can I get "blue" on top?我怎样才能在顶部获得“蓝色”?

For what it is worth, in ggplot2 version 2.2.1 the order of the stack is no longer determined by the row order in the data.frame.值得一提的是,在 ggplot2 版本 2.2.1 中,堆栈的顺序不再由 data.frame 中的行顺序决定。 Instead, it matches the order of the legend as determined by the order of levels in the factor.相反,它匹配由因子中的级别顺序确定的图例顺序。

d <- data.frame(
  y=c(0.1, 0.2, 0.7),
  cat = factor(c('No', 'Yes', 'NA'), levels = c('NA', 'Yes', 'No')))

# Original order
p1 <- ggplot(d, aes(x=1, y=y, fill=cat)) +
  geom_bar(stat='identity')

# Change order of rows
p2 <- ggplot(d[c(2, 3, 1), ], aes(x=1, y=y, fill=cat)) +
  geom_bar(stat='identity')

# Change order of levels
d$cat2 <- relevel(d$cat, 'Yes')
p3 <- ggplot(d, aes(x=1, y=y, fill=cat2)) +
  geom_bar(stat='identity') 

grid.arrange(p1, p2, p3, ncol=3)

It results in the below plot:结果如下图: 在此处输入图片说明

I've struggled with the same issue before.我之前一直在努力解决同样的问题。 It appears that ggplot stacks the bars based on their appearance in the dataframe.看来 ggplot 根据条形在数据框中的外观堆叠条形。 So the solution to your problem is to sort your data by the fill factor in the reverse order you want it to appear in the legend: bottom item on top of the dataframe, and top item on bottom:因此,您的问题的解决方案是按填充因子按您希望它出现在图例中的相反顺序对数据进行排序:数据框顶部的底部项目和底部的顶部项目:

ggplot(ts[order(ts$y, decreasing = T),],
       aes(z, x, fill=factor(y, levels=c("blue","white" )))) + 
  geom_bar(stat = "identity")

在此处输入图片说明

Edit: More illustration编辑:更多插图

Using sample data, I created three plots with different orderings of the dataframe, I thought that more fill-variables would make things a bit clearer.使用示例数据,我创建了三个具有不同数据框顺序的图,我认为更多的填充变量会使事情更清晰一些。

set.seed(123)
library(gridExtra)
df <- data.frame(x=rep(c(1,2),each=5),
                 fill_var=rep(LETTERS[1:5], 2),
                 y=1)
#original order   
p1 <- ggplot(df, aes(x=x,y=y,fill=fill_var))+
  geom_bar(stat="identity") + labs(title="Original dataframe")


#random order
p2 <- ggplot(df[sample(1:10),],aes(x=x,y=y,fill=fill_var))+
  geom_bar(stat="identity") + labs(title="Random order")
#legend checks out, sequence wird

#reverse order
p3 <- ggplot(df[order(df$fill_var,decreasing=T),],
             aes(x=x,y=y,fill=fill_var))+
  geom_bar(stat="identity") + labs(title="Reverse sort by fill")

plots <- list(p1,p2,p3)

do.call(grid.arrange,plots)

在此处输入图片说明

Use the group aethetic in the ggplot() call.ggplot()调用中使用group美学。 This ensures that all layers are stacked in the same way.这确保所有层都以相同的方式堆叠。

series <- data.frame(
  time = c(rep(1, 4),rep(2, 4), rep(3, 4), rep(4, 4)),
  type = rep(c('a', 'b', 'c', 'd'), 4),
  value = rpois(16, 10)
)

ggplot(series, aes(time, value, group = type)) +
  geom_col(aes(fill = type)) +
  geom_text(aes(label = type), position = "stack")

Messing with your data in order to make a graph look nice seems like a bad idea.为了使图表看起来更漂亮而使用您的数据似乎是个坏主意。 Here's an alternative that works for me when using position_fill() :这是使用position_fill()时对我有用的替代方法:

ggplot(data, aes(x, fill = fill)) + geom_bar(position = position_fill(reverse = TRUE)) 

The reverse = TRUE argument flips the order of the stacked bars. reverse = TRUE参数翻转堆叠条的顺序。 This works in position_stack also.这也适用于position_stack

I have the exactly same problem today.我今天遇到了完全相同的问题。 You can get blue on top by using order=-as.numeric() :您可以使用order=-as.numeric()获得blue

ggplot(ts, 
aes(z, x, fill=factor(y, levels=c("blue","white")), order=-as.numeric(y))) + 
geom_bar(stat = "identity")

I had a similar issue and got around by changing the level of the factor.我有一个类似的问题,并通过改变因子的水平来解决。 thought I'd share the code:以为我会分享代码:

library(reshape2)
library(ggplot2)

group <- c(
  "1",
  "2-4",
  "5-9",
  "10-14",
  "15-19",
  "20-24",
  "25-29",
  "30-34",
  "35-39",
  "40-44",
  "45-49"
)

xx <- factor(group, levels(factor(group))[c(1, 4, 11, 2, 3, 5:10)])

method.1 <- c(36, 14, 8, 8, 18, 1, 46, 30, 62, 34, 34)
method.2 <- c(21, 37, 45, 42, 68, 41, 16, 81, 51, 62, 14)
method.3 <- c(37, 46, 18, 9, 16, 79, 46, 45, 70, 42, 28)  
elisa.neg <- c(12, 17, 18, 6, 19, 14, 13, 13, 7, 4, 1)  
elisa.eq <- c(3, 6, 3, 14, 1, 4, 11, 13, 5, 3, 2)

test  <- data.frame(person = xx, 
                    "Mixture Model" = method.1,
                    "Censoring" = method.3,
                    "ELISA neg" = elisa.neg,
                    "ELISA eqiv" = elisa.eq) 

melted <- melt(test, "person")
melted$cat <- ifelse(melted$variable == "Mixture.Model", "1",
                     ifelse(melted$variable == "Censoring", "2", "3"))

melted$variable = factor(melted$variable, levels = levels(melted$variable)[c(1, 2, 4,3 )]) ## This did the trick of changing the order

ggplot(melted, aes(x = cat, y = value, fill = variable)) + 
  geom_bar(stat = 'identity') + facet_wrap(~ person) +
  theme(axis.ticks.x=element_blank(),
        axis.text.x=element_blank()) + 
  labs(title = "My Title",
       y = "Per cent", x = "Age Group", fill = "")

(Sorry, this is my data, I didn't reproduce using the data from the original post, hope it's ok!) (抱歉,这是我的数据,我没有使用原帖中的数据进行复制,希望没问题!)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM