Подтвердить что ты не робот

Проблема с 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

4b9b3361

Ответ 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