ggplot добавить горизонтальную линию внутри цикла [duplicate]

Очень простой подход, не зависящий от версии python, отсутствовал в уже заданных ответах, которые вы можете использовать большую часть времени (по крайней мере, я):

new_list = my_list * 1       #Solution 1 when you are not using nested lists

Однако, если my_list содержит другие контейнеры ( например, вложенных списков), вы должны использовать функцию глубокой печати, как другие, предложенные в ответах выше, из библиотеки копий. Например:

import copy
new_list = copy.deepcopy(my_list)   #Solution 2 when you are using nested lists

.Bonus: Если вы не хотите копировать элементы, используйте (ака мелкой копии):

new_list = my_list[:]

Давайте понимать разницу между решением # 1 и Solution # 2

>>> a = range(5)
>>> b = a*1
>>> a,b
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
>>> a[2] = 55 
>>> a,b
([0, 1, 55, 3, 4], [0, 1, 2, 3, 4])

Как вы можете видеть, решение № 1 отлично работало, когда мы не использовали вложенные списки. Давайте проверим, что произойдет, когда мы применим решение №1 к вложенным спискам.

>>> from copy import deepcopy
>>> a = [range(i,i+4) for i in range(3)]
>>> a
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> b = a*1
>>> c = deepcopy(a)
>>> for i in (a, b, c): print i   
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> a[2].append('99')
>>> for i in (a, b, c): print i   
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]]   #Solution#1 didn't work in nested list
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]       #Solution #2 - DeepCopy worked in nested list
9
задан user3799203 7 October 2014 в 13:18
поделиться

3 ответа

Причина, по которой это происходит, связана с «ленивой оценкой» 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]

9
ответ дан jlhoward 21 August 2018 в 23:07
поделиться
  • 1
    Благодарю. Я ценю объяснение того, как эта странность происходит с петлями и ggplot. Теперь я понимаю. Я думал, что это может быть что-то вроде этого - я попытался найти команду, которая нарисовала бы график как последний шаг каждого цикла (например, просто «g»), но я ничего не пробовал. Ваш код цикла - это то, что мне нужно. – user3799203 10 October 2014 в 02:27

Вы можете сделать это без петли:

df.2 <- melt(df)
gg <- ggplot(df.2, aes(x=topic, y=value))
gg <- gg + geom_violin(position="identity", aes(color=variable), alpha=0.3)
gg

enter image description here [/g0]

2
ответ дан hrbrmstr 21 August 2018 в 23:07
поделиться
  • 1
    Это не дает такой же график, как и у «успешных» OP. потому что скрипки масштабируются по-разному, когда вы создаете два слоя отдельно, когда вы группируете variable. Кроме того, следует, наверное, упомянуть, что для этого потребуется загрузить reshape2. – jlhoward 7 October 2014 в 23:43
  • 2
    Очень элегантно. При таком подходе, если я использую 'scale = "width & quot;" aes, сгруппированная, а не индивидуальная масштабируемая тонкость, о которой упоминает jlhoward, не имеет значения. – user3799203 10 October 2014 в 02:19

Просто избегайте использовать цикл for. Как насчет lapply:

g <- g + lapply(2:ncol(df), function(p) {
  geom_violin(aes(y = df[,p], colour = place[p-1]), alpha = 0.3)
})

EDIT: Это действительно не работает. У меня был p <- 2 в моей рабочей области, прежде чем запускать его, а затем он создал график только с данными Чикаго. Во всяком случае, принцип должен по-прежнему работать (хотя melt, вероятно, лучший вариант):

g <- ggplot(df, aes(x=factor(topic)))
g + lapply(place, function(p) {
  geom_violin(aes_string(y = p), alpha = 0.3, color = which(p==place))
})
2
ответ дан shadow 21 August 2018 в 23:07
поделиться
  • 1
    Вы попробовали это? Если я заменил цикл for OP на это, я получаю: Error in [. Data.frame (df, , p) : object 'p' not found. Если я сначала запустил цикл OP for (который создает переменную p), тогда запустите lapply(...), я получаю тот же результат, что и OP. – jlhoward 9 October 2014 в 16:49
  • 2
    Это не сработало для меня. Я получил тот же график, что и у меня с кодом моего плохого цикла. – user3799203 10 October 2014 в 02:37
Другие вопросы по тегам:

Похожие вопросы: