Проблема с ggplot2, geom_bar и position = "dodge": уложенная имеет правильные значения y, уклонение не
У меня есть понимание времени geom_bar()
и position="dodge"
. Я пытался сделать несколько гистограмм, иллюстрирующих две группы. Первоначально данные были получены из двух отдельных кадров данных. Per этот вопрос, я поместил свои данные в длинный формат. Мой пример:
test <- data.frame(names=rep(c("A","B","C"), 5), values=1:15)
test2 <- data.frame(names=c("A","B","C"), values=5:7)
df <- data.frame(names=c(paste(test$names), paste(test2$names)), num=c(rep(1,
nrow(test)), rep(2, nrow(test2))), values=c(test$values, test2$values))
Я использую этот пример, как он похож на пример расходов и бюджета. Расходы имеют много строк на коэффициент names
, тогда как бюджет имеет только один (одна сумма бюджета для каждой категории).
Для штабелированного штрихового графика это отлично работает:
ggplot(df, aes(x=factor(names), y=values, fill=factor(num))) +
geom_bar(stat="identity")
![stacked plot]()
В частности, обратите внимание на значения y max. Они представляют собой суммы данных из test
со значениями test2
, отображаемыми синим цветом сверху.
В соответствии с другими вопросами, которые я прочитал, мне просто нужно добавить position="dodge"
, чтобы сделать его бок о бок, а также сложным:
ggplot(df, aes(x=factor(names), y=values, fill=factor(num))) +
geom_bar(stat="identity", position="dodge")
![dodged]()
Это выглядит великолепно, но обратите внимание на новые значения max y. Похоже, что он просто принимает значение max y с каждого уровня факторов имен от test
для значения y. Он больше не суммирует их.
По другим вопросам (например этот и этот, я также попытался добавить group=
без успеха (создает тот же самый уклоненный график, что и выше):
ggplot(df, aes(x=factor(names), y=values, fill=factor(num), group=factor(num))) +
geom_bar(stat="identity", position="dodge")
Я не понимаю, почему многослойные работы отлично работают, а уклонение не просто ставит их бок о бок, а не сверху.
ETA: Я нашел недавний вопрос об этом в группе ggplot google с предложением добавить alpha=0.5
, чтобы узнать, что происходит. Дело не в том, что ggplot принимает максимальное значение от каждой группы; он фактически перекрывает планшеты поверх друг друга для каждого значения.
Кажется, что при использовании position="dodge"
ggplot ожидает только одного y за x. Я связался с Уинстоном Чангом, разработчиком ggplot, чтобы подтвердить это, а также узнать, можно ли это изменить, поскольку я не вижу преимущества.
Кажется, что stat="identity"
должен сказать ggplot, чтобы подсчитать y=val
, переданный внутри aes()
, вместо отдельных счетчиков, который происходит без stat="identity"
и при передаче значения y.
В настоящее время обходной путь кажется (для исходного df выше) агрегировать, так что только один y на x:
df2 <- aggregate(df$values, by=list(df$names, df$num), FUN=sum)
p <- ggplot(df2, aes(x=Group.1, y=x, fill=factor(Group.2)))
p <- p + geom_bar(stat="identity", position="dodge")
p
![correct]()
Ответы
Ответ 1
Я думаю, проблема в том, что вы хотите складывать в значениях группы num
и уклоняться от значений num
.
Это может помочь посмотреть, что происходит, когда вы добавляете контур в бары.
library(ggplot2)
set.seed(123)
df <- data.frame(
id = 1:18,
names = rep(LETTERS[1:3], 6),
num = c(rep(1, 15), rep(2, 3)),
values = sample(1:10, 18, replace=TRUE)
)
По умолчанию множество баров сложено - вы просто не видите, что они разделены, если у вас нет контура:
# Stacked bars
ggplot(df, aes(x=factor(names), y=values, fill=factor(num))) +
geom_bar(stat="identity", colour="black")
![Stacked bars]()
Если вы увертываете, вы получаете бары, которые уклоняются от значений num
, но может быть несколько баров в пределах каждого значения num
:
# Dodged on 'num', but some overplotted bars
ggplot(df, aes(x=factor(names), y=values, fill=factor(num))) +
geom_bar(stat="identity", colour="black", position="dodge", alpha=0.1)
![Dodged on num]()
Если вы добавите id
в качестве группировки var, он уклонится от всех из них:
# Dodging with unique 'id' as the grouping var
ggplot(df, aes(x=factor(names), y=values, fill=factor(num), group=factor(id))) +
geom_bar(stat="identity", colour="black", position="dodge", alpha=0.1)
![Dodge all bars]()
Я думаю, что вы хотите, чтобы оба уклонились и стекали, но вы не можете обойти оба.
Поэтому лучше всего суммировать данные самостоятельно.
library(plyr)
df2 <- ddply(df, c("names", "num"), summarise, values = sum(values))
ggplot(df2, aes(x=factor(names), y=values, fill=factor(num))) +
geom_bar(stat="identity", colour="black", position="dodge")
![Summarized beforehand]()