Согласованная ширина для geom_bar в случае отсутствия данных
Есть ли способ установить постоянную ширину для geom_bar()
в случае отсутствия данных в примере временных рядов ниже? Я пробовал установить width
в aes()
без везения. Сравните май '11 по июнь '11 ширину полос на графике ниже примера кода.
colours <- c("#FF0000", "#33CC33", "#CCCCCC", "#FFA500", "#000000" )
iris$Month <- rep(seq(from=as.Date("2011-01-01"), to=as.Date("2011-10-01"), by="month"), 15)
colours <- c("#FF0000", "#33CC33", "#CCCCCC", "#FFA500", "#000000" )
iris$Month <- rep(seq(from=as.Date("2011-01-01"), to=as.Date("2011-10-01"), by="month"), 15)
d<-aggregate(iris$Sepal.Length, by=list(iris$Month, iris$Species), sum)
d$quota<-seq(from=2000, to=60000, by=2000)
colnames(d) <- c("Month", "Species", "Sepal.Width", "Quota")
d$Sepal.Width<-d$Sepal.Width * 1000
g1 <- ggplot(data=d, aes(x=Month, y=Quota, color="Quota")) + geom_line(size=1)
g1 + geom_bar(data=d[c(-1:-5),], aes(x=Month, y=Sepal.Width, width=10, group=Species, fill=Species), stat="identity", position="dodge") + scale_fill_manual(values=colours)
![plot]()
Ответы
Ответ 1
Самый простой способ - дополнить свой набор данных, чтобы каждая комбинация присутствовала, даже если она имеет NA
в качестве ее значения. Принимая более простой пример (поскольку у вас много ненужных функций):
dat <- data.frame(a=rep(LETTERS[1:3],3),
b=rep(letters[1:3],each=3),
v=1:9)[-2,]
ggplot(dat, aes(x=a, y=v, colour=b)) +
geom_bar(aes(fill=b), stat="identity", position="dodge")
![enter image description here]()
Это показывает поведение, которое вы пытаетесь избежать: в группе "B" нет группы "a", поэтому полосы более широкие. Дополните dat
фреймворком данных со всеми комбинациями a
и b
:
dat.all <- rbind(dat, cbind(expand.grid(a=levels(dat$a), b=levels(dat$b)), v=NA))
ggplot(dat.all, aes(x=a, y=v, colour=b)) +
geom_bar(aes(fill=b), stat="identity", position="dodge")
![enter image description here]()
Ответ 2
У меня была такая же проблема, но я искал решение, которое работает с трубой (%>%
). Использование tidyr::spread
и tidyr::gather
из tidyverse
делает трюк. Я использую те же данные, что и @Brian Diggs, но с именами прописных букв, которые не имеют двойных имен переменных при преобразовании в широкий:
library(tidyverse)
dat <- data.frame(A = rep(LETTERS[1:3], 3),
B = rep(letters[1:3], each = 3),
V = 1:9)[-2, ]
dat %>%
spread(key = B, value = V, fill = NA) %>% # turn data to wide, using fill = NA to generate missing values
gather(key = B, value = V, -A) %>% # go back to long, with the missings
ggplot(aes(x = A, y = V, fill = B)) +
geom_col(position = position_dodge())
Edit:
На самом деле это еще более простое решение этой проблемы в сочетании с трубой. Использовать tidyr::complete
дает тот же результат в одной строке:
dat %>%
complete(A, B) %>%
ggplot(aes(x = A, y = V, fill = B)) +
geom_col(position = position_dodge())