上下文
我有一个数据集,其中使用类别和子类别描述观察。子类别是这样的,即给定的一个只链接到一个类别(想想“类别〜汽车品牌”和“子类别〜汽车模型”)。
想象一下,我计算每天通过窗户可以看到的汽车数量。我应该得到一个与此类似的数据集:
_______________________________________________________
| 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个子类别)。这使得这种解决方案不“可用”。
问题
如何制作这样的图表,其中每个条形图(〜品牌)有一种颜色(蓝色/红色/黄色),每个子类别都有单色阴影/色调变化(深蓝色/中蓝色/浅蓝色;深红色/ ...... )?
(实际上,子类别是汽车模型,因此特定于每个品牌 - 而不是通用/多品牌类别,例如“品牌中观察到的最多模型”。此外,每个品牌的模型数量各不相同。)
示例
我可以使用以下代码生成结果(请参阅示例底部的数据):
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
答案 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)
我还没弄清楚为什么传奇按此顺序出现,但您可以更改标签的顺序,也可以完全放弃图例,具体取决于您所需的输出。希望这不是太复杂!