ggplot2 в цикле показывает только первый и последний ввод данных [dубликат]

Резюме: Когда я использую цикл «для» для добавления слоев в график скрипки (в ggplot), единственным добавленным слоем является тот, который создается последней итерацией цикла.

Подробности: Я пытаюсь создать скриптовые графики с перекрывающимися слоями, чтобы показать, насколько оценивают распределения, делают или делают не перекрываются для нескольких ответов опроса, стратифицированных по месту. Я хочу, чтобы иметь возможность включать любое количество мест, поэтому у меня есть один столбец с помощью dataframe для каждого места, и я пытаюсь использовать цикл «для» для создания одного слоя ggplot для каждого места. Но этот цикл только добавляет слой из конечной итерации цикла.

Этот код иллюстрирует проблему, а некоторые предлагаемые подходы не удались:

library(ggplot2) 

# Create a dataframe with 500 random normal values for responses to 3 survey questions from two cities
topic <- c("Poverty %","Mean Age","% Smokers")
place <- c("Chicago","Miami")
n <- 500
mean <- c(35,  40,58,  50, 25,20)
var  <- c( 7, 1.5, 3, .25, .5, 1)
df <- data.frame( topic=rep(topic,rep(n,length(topic)))
                 ,c(rnorm(n,mean[1],var[1]),rnorm(n,mean[3],var[3]),rnorm(n,mean[5],var[5]))
                 ,c(rnorm(n,mean[2],var[2]),rnorm(n,mean[4],var[4]),rnorm(n,mean[6],var[6]))
                )
names(df)[2:dim(df)[2]] <- place  # Name those last two columns with the corresponding place name.
head(df) 

# This "for" loop seems to only execute the final loop (i.e., where p=3)
g <- ggplot(df, aes(factor(topic), df[,2]))
for (p in 2:dim(df)[2]) {
  g <- g + geom_violin(aes(y = df[,p], colour = place[p-1]), alpha = 0.3)
}
g

# But mimicing what the for loop does in explicit code works fine, resulting in both "place"s being displayed in the graph.
g <- ggplot(df, aes(factor(topic), df[,2]))
g <-   g + geom_violin(aes(y = df[,2], colour = place[2-1]), alpha = 0.3)
g <-   g + geom_violin(aes(y = df[,3], colour = place[3-1]), alpha = 0.3)
g

## per http://stackoverflow.com/questions/18444620/set-layers-in-ggplot2-via-loop , I tried 
g <- ggplot(df, aes(factor(topic), df[,2]))
for (p in 2:dim(df)[2]) {
  df1 <- df[,c(1,p)]
  g <- g + geom_violin(aes(y = df1[,2], colour = place[p-1]), alpha = 0.3)
}
g
# but got the same undesired result

# per http://stackoverflow.com/questions/15987367/how-to-add-layers-in-ggplot-using-a-for-loop , I tried
g <- ggplot(df, aes(factor(topic), df[,2]))
for (p in names(df)[-1]) {
  cat(p,"\n")
  g <- g + geom_violin(aes_string(y = p, colour = p), alpha = 0.3)  # produced this error: Error in unit(tic_pos.c, "mm") : 'x' and 'units' must have length > 0
  # g <- g + geom_violin(aes_string(y = p            ), alpha = 0.3)  # produced this error: Error: stat_ydensity requires the following missing aesthetics: y
}
g
# but that failed to produce any graphic, per the errors noted in the "for" loop above
9
задан 7 October 2014 в 17:18

2 ответа

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

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

2
ответ дан 15 August 2018 в 16:39
  • 1
    Это не дает такой же график, как и у «успешных» OP. потому что скрипки масштабируются по-разному, когда вы создаете два слоя отдельно, когда вы группируете variable. Кроме того, следует, наверное, упомянуть, что для этого потребуется загрузить reshape2. – jlhoward 8 October 2014 в 03:43
  • 2
    Очень элегантно. При таком подходе, если я использую 'scale = "width & quot;" aes, сгруппированная, а не индивидуальная масштабируемая тонкость, о которой упоминает jlhoward, не имеет значения. – user3799203 10 October 2014 в 06: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
ответ дан 15 August 2018 в 16:39
  • 1
    Вы попробовали это? Если я заменил цикл for OP на это, я получаю: Error in [. Data.frame (df, , p) : object 'p' not found. Если я сначала запустил цикл OP for (который создает переменную p), тогда запустите lapply(...), я получаю тот же результат, что и OP. – jlhoward 9 October 2014 в 20:49
  • 2
    Это не сработало для меня. Я получил тот же график, что и у меня с кодом моего плохого цикла. – user3799203 10 October 2014 в 06:37

Другие вопросы по тегам:

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