堆积条形图:如果每个子类别(填充)都是唯一的,该怎么办?

时间:2018-06-16 22:15:40

标签: r ggplot2 geom-bar

上下文
我有一个数据集,其中使用类别和子类别描述观察。子类别是这样的,即给定的一个只链接到一个类别(想想“类别〜汽车品牌”和“子类别〜汽车模型”)。

想象一下,我计算每天通过窗户可以看到的汽车数量。我应该得到一个与此类似的数据集:

 _______________________________________________________
| Date      | Brand         | Model         | Count     |
|===========:===============:===============:===========|
| 18-01-01  | Ford          | Model T       | 1         |
| 18-01-01  | Ford          | Focus         | 13        |
| 18-01-01  | Tesla         | Model X       | 17        |
| 18-01-02  | Ford          | Model T       | 1         |
| 18-01-02  | Honda         | Civic         | 210       |
| _         | _             | _             | _         |
|___________|_______________|_______________|___________|

问题
我想创建一个(水平)条形图,显示按类别分组的条目数(即每个条形代表一个品牌)。此外,我想让每个条形图按每个模型进行细分(即最接近条形的轴部分代表品牌最多的模型,然后是计算次数最多的模型等)。

我可以生成这样的图形,但每个子类别都表示为单个图例项目(参见下面示例中的第一个图形)。但在我的真实例子中,我有十几个类别 - 每个类别使用十几个子类别(因此总共约150个子类别)。这使得这种解决方案不“可用”。

enter image description here

问题
如何制作这样的图表,其中每个条形图(〜品牌)有一种颜色(蓝色/红色/黄色),每个子类别都有单色阴影/色调变化(深蓝色/中蓝色/浅蓝色;深红色/ ...... )?
(实际上,子类别是汽车模型,因此特定于每个品牌 - 而不是通用/多品牌类别,例如“品牌中观察到的最多模型”。此外,每个品牌的模型数量各不相同。)

enter image description here

示例

我可以使用以下代码生成结果(请参阅示例底部的数据):

library(ggplot2)
df = read.csv('fake-data.csv', header = TRUE)
df <- df[order(df$car_brand, decreasing = FALSE),]
ggplot(df, aes(x=car_brand, y=count, fill = car_model)) +
  geom_bar(position = 'stack', stat = 'identity') +
  coord_flip()

但是,我为每个模型获得了单一颜色和图例条目。 我希望每个品牌都有一种颜色,每种型号的品牌都有不同颜色的色调/色调。

以下是fake-data.csv的内容,显然是假数据:

month,car_brand,car_model,count
18-01,Tesla,Model X,8
18-01,Ford,Model T,11
18-01,Ford,Focus,9
18-01,Ford,Focus,19
18-01,Tesla,Model 3,8
18-01,BMW,1 series,4
18-01,Ford,Model T,18
18-01,Honda,Civic,13
18-01,Ford,Model T,9
18-01,Tesla,Model S,18
18-01,BMW,1 series,6
18-01,Ford,Focus,10
18-01,Honda,Civic,9
18-01,Audi,A6,14
18-01,Audi,R8,19
18-01,Ford,Focus,13
18-01,BMW,1 series,7
18-01,Tesla,Model 3,12
18-01,BMW,1 series,11
18-01,BMW,1 series,9
18-01,BMW,1 series,4
18-01,BMW,1 series,11
18-01,Ford,Model T,17
18-01,Honda,Civic,10
18-01,BMW,1 series,9
18-01,Ford,Focus,19
18-01,Honda,Civic,9
18-01,Ford,Focus,15
18-01,Audi,A8,12
18-01,Tesla,Model X,6
18-01,Honda,Civic,14
18-01,BMW,1 series,16
18-01,Tesla,Model X,18
18-01,Tesla,Model X,16
18-01,Audi,TT,20
18-01,Tesla,Model 3,9
18-01,Tesla,Model X,21
18-01,BMW,1 series,9
18-01,Audi,A8,18
18-01,BMW,1 series,2
18-01,Ford,Focus,2
18-01,Honda,Civic,7
18-01,Tesla,Model X,9
18-01,Honda,Civic,3
18-01,BMW,1 series,5
18-01,Ford,Focus,14
18-01,Honda,Civic,4
18-01,Tesla,Model S,4
18-01,Honda,Civic,7
18-01,Honda,Civic,13
18-01,Tesla,Model 3,3
18-01,Tesla,Model 3,9
18-01,BMW,1 series,13
18-01,Ford,Model T,11
18-01,Ford,Focus,10
18-01,Tesla,Model S,18
18-01,Audi,Q3,6
18-01,Audi,R8,13
18-01,Tesla,Model X,21
18-01,BMW,1 series,13
18-01,Ford,Focus,17
18-01,Tesla,Model X,14
18-01,Audi,TT,3
18-01,Ford,Model T,11
18-01,Honda,Civic,7
18-01,Ford,Focus,4
18-01,Honda,accord,6
18-01,Ford,Focus,10
18-01,Ford,Model T,10
18-01,Honda,Civic,15
18-01,Ford,Model T,2
18-01,Tesla,Model X,10
18-01,Ford,Focus,11
18-01,Tesla,Model X,14
18-01,Honda,Civic,13
18-01,BMW,1 series,19
18-01,BMW,1 series,21
18-01,Ford,Focus,8
18-01,Tesla,Model X,12
18-01,Honda,Civic,5
18-01,Honda,Civic,14
18-01,Honda,Civic,17
18-01,Audi,R8,16
18-01,Honda,Civic,12
18-01,Audi,A6,20
18-01,Tesla,Model X,4
18-01,Audi,TT,4
18-01,Ford,Focus,16
18-01,Audi,Q3,16
18-01,BMW,1 series,12
18-01,Audi,A8,18
18-01,Honda,Civic,1
18-01,Audi,A8,7
18-01,Audi,Q3,10
18-01,Tesla,Model X,18
18-01,Ford,Focus,19
18-01,Ford,Model T,2
18-01,Tesla,Model 3,15
18-01,Ford,Model T,13
18-01,Ford,Model T,2
18-01,Audi,Q3,14
18-01,BMW,1 series,4
18-01,Audi,R8,1
18-01,Honda,Civic,2
18-01,Tesla,Model 3,4
18-01,BMW,1 series,16
18-01,Audi,A8,5
18-01,Ford,Model T,18
18-01,Tesla,Model X,21
18-01,Ford,Focus,4
18-01,Ford,Focus,7
18-01,BMW,1 series,16
18-01,Tesla,Model X,16
18-01,Tesla,Model 3,14
18-01,BMW,1 series,8
18-01,BMW,1 series,13
18-01,Tesla,Model 3,7
18-01,Ford,Focus,21
18-01,BMW,1 series,14
18-01,BMW,1 series,10
18-01,Ford,Focus,11
18-01,Tesla,Model 3,13
18-01,Honda,Civic,4
18-01,Ford,Focus,11
18-01,Ford,Focus,8
18-01,BMW,1 series,18
18-01,Honda,Civic,18
18-01,Honda,Civic,15
18-01,Ford,Focus,9
18-01,Tesla,Model 3,4
18-01,BMW,1 series,5
18-01,Tesla,Model S,5
18-01,Audi,TT,12
18-01,Honda,Civic,17
18-01,BMW,1 series,9
18-01,Honda,Civic,7
18-01,Tesla,Model 3,15
18-01,Audi,A8,21
18-01,Ford,Model T,21
18-01,Ford,Model T,9
18-01,BMW,1 series,18
18-01,Tesla,Model 3,7
18-01,BMW,1 series,15
18-01,BMW,1 series,2
18-01,Ford,Model T,18
18-01,Audi,R8,17
18-01,Tesla,Model 3,3
18-01,Audi,A8,9
18-01,BMW,1 series,10
18-01,Audi,Q3,4
18-01,BMW,1 series,8
18-01,Honda,accord,19
18-01,Tesla,Model S,6
18-01,Audi,TT,18
18-01,Audi,Q3,21
18-01,Tesla,Model S,3
18-01,Tesla,Model S,9
18-01,Audi,Q3,1
18-01,Tesla,Model X,18
18-01,Honda,Civic,8
18-01,Audi,R8,14
18-01,Honda,Civic,21
18-01,Tesla,Model X,9
18-01,Audi,TT,16
18-01,Audi,A8,19
18-01,Ford,Focus,2
18-01,BMW,1 series,12
18-01,Ford,Model T,9
18-01,Tesla,Model X,9
18-01,Audi,R8,18
18-01,Honda,Civic,3
18-01,Honda,accord,7
18-01,Audi,A6,13
18-01,Audi,A8,13
18-01,Ford,Focus,8
18-01,Honda,accord,10
18-01,Audi,R8,20
18-01,Honda,Civic,18
18-01,Ford,Focus,7
18-01,Audi,R8,10
18-01,Audi,A6,13
18-01,Honda,Civic,4
18-01,Audi,A8,7
18-01,Audi,Q3,15
18-01,Honda,Civic,10
18-01,Audi,A8,6
18-01,Honda,Civic,1
18-01,Tesla,Model 3,21
18-01,Ford,Model T,7
18-01,BMW,1 series,6
18-01,Honda,Civic,4
18-01,Audi,A6,12
18-01,Honda,Civic,6
18-01,Tesla,Model S,17
18-01,Tesla,Model S,2
18-01,Tesla,Model X,6
18-01,Audi,A8,2
18-01,Tesla,Model 3,14
18-01,BMW,1 series,4
18-01,BMW,1 series,20
18-01,Honda,accord,17
18-01,Honda,Civic,14
18-01,BMW,1 series,16
18-01,Audi,A8,17
18-01,Audi,A6,11
18-01,Ford,Model T,1
18-01,BMW,1 series,18
18-01,Tesla,Model 3,11
18-01,Honda,Civic,21

2 个答案:

答案 0 :(得分:2)

这是一种映射到alpha的方式 - 它是我所知道的最接近你想要的东西。

library(tidyverse)
df %>%
  group_by(car_brand, car_model) %>%
  summarise_at(vars(count), sum) %>%
  group_by(car_brand) %>%
  mutate(
    model_rank = car_model %>% rank(),
  ) %>%
  ggplot(aes(x = car_brand, y = count, fill = car_brand, alpha = model_rank)) +
  scale_alpha_continuous(range = c(1, .25)) + 
  theme(legend.position = 'none') + 
  geom_bar(position = 'stack', stat = 'identity') + 
  coord_flip()

答案 1 :(得分:1)

这是一个比实际需要更复杂的解决方案。在大多数情况下,我只是推荐@Melissa Key的答案,并将其映射到alpha,但我很想知道可能会扩展的方法。这样可以将多个调色板粘贴在一起,每个调色板一个,并根据make为此向量中的每个项目指定名称。

我做的第一件事是按生产和模型总结数据框的总计数。然后我将make和model都制作成因子,然后使用forcats函数对它们进行排序以按make排序(只是按字母顺序排列,但你可以改变它),然后是最常见的模型。

library(tidyverse)
library(RColorBrewer)

df_sums <- df %>%
  group_by(car_brand, car_model) %>%
  summarise(count = sum(count)) %>%
  ungroup() %>%
  mutate(car_brand = as.factor(car_brand)) %>%
  mutate(car_model = as.factor(car_model) %>% fct_reorder2(car_brand, count, .desc = T)) %>%
  arrange(car_brand, car_model)

df_sums
#> # A tibble: 13 x 3
#>    car_brand car_model count
#>    <fct>     <fct>     <int>
#>  1 Audi      A8          154
#>  2 Audi      R8          128
#>  3 Audi      Q3           87
#>  4 Audi      A6           83
#>  5 Audi      TT           73
#>  6 BMW       1 series    413
#>  7 Ford      Focus       284
#>  8 Ford      Model T     189
#>  9 Honda     Civic       346
#> 10 Honda     accord       59
#> 11 Tesla     Model X     250
#> 12 Tesla     Model 3     169
#> 13 Tesla     Model S      82

从那时起,我沿着数据框的分割版本和调色板名称向量进行映射,因此我可以按名称获取Color Brewer调色板,每个调色板一个。单色调顺序刻度非常适合这种方式,并且便于取出。这里的问题是你需要给出brewer.pal中的颜色数量,但这至少会返回3种颜色,所以你需要将颜色矢量子集化,以便给出正确数量的颜色。在每个调色板有更多颜色或使用brewer.pal以外的其他内容来获取调色板的情况下,这不是必需的。然后我将颜色调色板的名称设置为模型的名称,以便在scale_fill_manual中保持顺序。

pals <- c("Blues", "Purples", "Greens", "Reds", "Oranges")

colors <- df_sums %>%
  split(.$car_brand) %>%
  map2(pals, function(d, pal) {
    n <- nrow(d)
    brewer.pal(n, pal)[1:n] %>%
      setNames(d$car_model)
  }) %>%
  reduce(c)

head(colors)
#>        A8        R8        Q3        A6        TT  1 series 
#> "#EFF3FF" "#BDD7E7" "#6BAED6" "#3182BD" "#08519C" "#EFEDF5"

df_sums %>%
  ggplot(aes(x = car_brand, y = count, fill = car_model)) +
    geom_col() +
    coord_flip() +
    scale_fill_manual(values = colors)

我还没弄清楚为什么传奇按此顺序出现,但您可以更改标签的顺序,也可以完全放弃图例,具体取决于您所需的输出。希望这不是太复杂!