Причина, по которой это происходит, связана с «ленивой оценкой» ggplot
. Это обычная проблема, когда ggplot
используется таким образом (делая слои отдельно в цикле, вместо того, чтобы иметь для него ggplot
, как в решении @ hrbrmstr).
ggplot
сохраняет аргументы aes(...)
как выражения и оценивает их только при отображении графика. Таким образом, в ваших циклах, что-то вроде
aes(y = df[,p], colour = place[p-1])
сохраняется, как есть, и оценивается при визуализации графика после завершения цикла. На этом этапе p = 3, поэтому все графики отображаются с p = 3.
Таким образом, «правильный» способ сделать это - использовать melt(...)
в пакете reshape2
, чтобы конвертировать ваши данные от широкого до длинного формата, и пусть ggplot
управляет слоями для вас. Я ставлю «правильно» в кавычки, потому что в этом конкретном случае есть тонкость. При расчете распределений для скрипки с использованием кадра расплавленных данных ggplot
использует общую сумму (как для Чикаго, так и для Майами) в качестве шкалы. Если вы хотите, чтобы скрипки были основаны на частоте, масштабируемой по отдельности, вам нужно использовать петли (к сожалению).
Путь вокруг ленивой проблемы оценки заключается в том, чтобы ссылаться на индекс цикла в определении data=...
. Это not сохраняется как выражение, фактические данные хранятся в определении графика. Поэтому вы можете сделать это:
g <- ggplot(df,aes(x=topic))
for (p in 2:length(df)) {
gg.data <- data.frame(topic=df$topic,value=df[,p],city=names(df)[p])
g <- g + geom_violin(data=gg.data,aes(y=value, color=city))
}
g
[/g2]
, который дает тот же результат, что и ваш. Обратите внимание, что индекс p
не отображается в aes(...)
.
Обновление: примечание о scale="width"
(упомянутое в комментарии). Это приводит к тому, что все скрипки имеют одинаковую ширину (см. Ниже), что не такое же масштабирование, как в исходном коде OP. IMO - это отличный способ визуализировать данные, так как предполагает, что в группе Чикаго имеется гораздо больше данных.
ggplot(gg) +geom_violin(aes(x=topic,y=value,color=variable),
alpha=0.3,position="identity",scale="width")
[/g3]