在 Plotly 中的堆叠条形图:如何控制每个堆叠中条的顺序

5

我正在尝试在plotly中订购堆叠条形图,但它没有遵循我在数据帧中传递的顺序。

最好使用一些模拟数据来展示:

library(dplyr)
library(plotly)
cars <- sapply(strsplit(rownames(mtcars), split = " "), "[", i = 1)
dat <- mtcars
dat <- cbind(dat, cars, stringsAsFactors = FALSE)
dat <- dat %>% 
         mutate(carb = factor(carb)) %>%
         distinct(cars, carb) %>% 
         select(cars, carb, mpg) %>% 
         arrange(carb, desc(mpg))
plot_ly(dat) %>% 
  add_trace(data = dat, type = "bar", x = carb, y = mpg, color = cars) %>%  
  layout(barmode = "stack") 

生成的图表没有按顺序排列,我希望将具有最大平均每加仑英里数(mpg)的汽车堆叠在每个汽缸组的底部。你有什么想法吗?

enter image description here

2个回答

3

此处所指出的,这个问题是由于在用于颜色分组的列(在本例中为cars)中存在重复值所导致的。如已指示,条形图的排序可以通过将颜色按唯一名称的列进行分组来解决。但是,这样做会产生一些不必要的副作用:

  1. 同一制造商的不同型号汽车将显示不同的颜色(这不是您想要的 - 您想按制造商进行着色)
  2. 图例中将有比您想要的更多的条目,即每种汽车型号而不是每个制造商一个。

我们可以通过以下方法绕过此问题:a) 从永远不会被显示的虚拟数据创建图例(在下面的代码中使用add_trace(type = "bar", x = 0, y = 0...),并b) 使用colors=参数手动设置每个类别的颜色。我在下面的代码中使用彩虹调色板来展示原理。您也可以选择更漂亮的颜色。

dat$unique.car <- make.unique(as.character(dat$cars))
dat2 <- data.frame(cars=levels(as.factor(dat$cars)),color=rainbow(nlevels(as.factor(dat$cars))))
dat2[] <- lapply(dat2, as.character)
dat$color <- dat2$color[match(dat$cars,dat2$cars)]

plot_ly() %>% 
  add_trace(data=dat2, type = "bar", x = 0, y = 0, color = cars, colors=color, showlegend=T) %>%  
  add_trace(data=dat, type = "bar", x = carb, y = mpg, color = unique.car, colors=color, showlegend=F, marker=list(line=list(color="black", width=1))) %>%  
  layout(barmode = "stack", xaxis = list(range=c(0.4,8.5))) 

enter image description here


感谢 @dww。我更新了示例,删除了分组列(cars)中的重复值。 - stu
@stu,不,仍然存在重复项。如果你消除了重复项或按照上述方法操作,它就会起作用。请注意,distinct(cars, carb)只会删除这两个相同的重复行。这不是你想要的。 - dww
是的,我明白了。谢谢@dww,我只需要找到一个不错的配色方案就可以了。 - stu

2

解决这个问题的一种方法是给每个汽车型号赋予唯一的名称,并在plotly中使用它,但这会使图例更加混乱并影响颜色映射。以下是一些选择:

dat$carsID <- make.unique(as.character(dat$cars))
# dat$carsID <- apply(dat, 1, paste0, collapse = " ") # alternative

plot_ly(dat) %>% 
  add_trace(data = dat, type = "bar", x = carb, y = mpg, color = carsID) %>%  
  layout(barmode = "stack") 

plot_ly(dat) %>% 
  add_trace(data = dat, type = "bar", x = carb, y = mpg, color = carsID,
            colors = rainbow(length(unique(carsID)))) %>%  
  layout(barmode = "stack")

明天我会再看一下,看看能否改进图例和颜色映射。


还需要确保数据按升序排列,即使用arrange(carb, mpg)而不是arrange(carb, desc(mpg)) - Adam Quek
感谢@jota。抱歉,我的示例代码中有一个错误,我已经删除了每个汽化器类别中的重复车辆。我得到了相同的结果。 - stu
1
@AdamQuek,数据已经正确堆叠,如x1所示。 - stu
@stu 给所有的汽车型号命名独特的名称可能会帮助你解决问题,但它会改变传说,并且每个品牌的汽车将有多种颜色(即每辆丰田车将是不同的颜色)。我明天再看一下这个问题。 - Jota
感谢@Jota,在我的真实数据中,我有30个实体分属于14个类别,所以在图例和颜色方面遇到了问题。这似乎是plotly中的一个bug,因为ggplot会尊重顺序。 - stu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接