2016-03-28 7 views
1

Я пытаюсь итеративно строить все возможные графики моих данных, окрашенных каждым столбцом в таблице.Как бороться с закрытием в R?

До сих пор у меня есть этот код:

# ----- next is a function taken from http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2)/ 
    # --- not relevant to the question, my code is in the end of the snippet 
    library(ggplot2) 
    multiplot <- function(..., plotlist=NULL, file, cols=1, layout=NULL) { 
    library(grid) 

    # Make a list from the ... arguments and plotlist 
    plots <- c(list(...), plotlist) 

    numPlots = length(plots) 

    # If layout is NULL, then use 'cols' to determine layout 
    if (is.null(layout)) { 
    # Make the panel 
    # ncol: Number of columns of plots 
    # nrow: Number of rows needed, calculated from # of cols 
    layout <- matrix(seq(1, cols * ceiling(numPlots/cols)), 
        ncol = cols, nrow = ceiling(numPlots/cols)) 
    } 

    if (numPlots==1) { 
    print(plots[[1]]) 

    } else { 
    # Set up the page 
    grid.newpage() 
    pushViewport(viewport(layout = grid.layout(nrow(layout), ncol(layout)))) 

    # Make each plot, in the correct location 
    for (i in 1:numPlots) { 
     # Get the i,j matrix positions of the regions that contain this subplot 
     matchidx <- as.data.frame(which(layout == i, arr.ind = TRUE)) 

     print(plots[[i]], vp = viewport(layout.pos.row = matchidx$row, 
             layout.pos.col = matchidx$col)) 
    } 
    } 
} 

#---------------------------------------------------------------- 
temp23_before6 <- data.frame(TIME = c(1, 2, 3, 4, 5), 
         VALUE = c(1, 2, 3, 4, 5), 
         P = c(1, 2, 3, 2, 1), 
         D = c(4, 5, 6, 7, 8)) 
i <- 1 
p <- list() 
for (col in names(temp23_before6)) { 
    l <-length(unique(temp23_before6[, col])) 
    if (l < 20 && l > 1) { 
    cc <- col 
    p[[i]] <- ggplot(temp23_before6, aes(TIME, VALUE, colour=factor(temp23_before6[, cc]))) + 
       geom_point() + labs(title=col) 

    i <- i + 1 
    } 
} 
multiplot(plotlist = p, cols = as.integer(sqrt(i))) 

К сожалению cc не изменяется из-за закрытия, и я получаю все участки точно так же. Обычный трюк, который работает с другими языками - назначает col локальной переменной - не работает. Как заставить работать в R?

Обновление Обновленный код, поэтому пример можно запустить в новом R env. Я ожидаю, что эти четыре сюжета будут иметь разный цвет. Два из них Time и Value должно быть очевидно из одного цвета, а два других P и D должны иметь разные цвета, определяемые P = c(1, 2, 3, 2, 1), D = c(4, 5, 6, 7, 8), так D должны иметь 5 различных цветов, и P должны иметь только 3

+0

'c' является объектом, уже существует в R и не должен быть перезаписан. Учитывая, что вы пишете цикл 'for', нет никакой разницы между« локальными »и« глобальными »переменными, потому что вы не вводите другую область. Я не понимаю, почему вам нужно назначить 'col'' 'c' вообще, учитывая, что он вызывается только один раз и может быть вызван только с помощью' col'. Работает ли ваш код, если вы замените 'color = factor (temp23_before6 [, c])' на 'color = factor (temp23_before6 [, col])'? – brittenb

+0

@Batanichek Полностью пропустил это. Но это, к сожалению, не помогает – Archeg

+0

@brittenb Нет, если я заменю его на 'col', он все равно сделает то же самое.Обычным трюком на других языках (C#, Java) является создание локальной переменной для закрытия, поэтому для каждого для запуска будет отдельная локальная переменная (так что у вас есть такое же количество локальных переменных, сколько и в общем массиве, поэтому каждый для запуска отдельно закрывается над собственным экземпляром 'c'. Но, видимо, это не работает в R – Archeg

ответ

6

Эта проблема имеет больше общего с программированием в пределах hadlyverse. Мы делаем два изменения, 1) добавить aes_string чтобы можно было провести оценку в рамках ggplot вызова и 2) очистить легенду назвать колонкой красящего:

p[[i]] <- ggplot(temp23_before6, aes_string("TIME", "VALUE", 
      colour=factor(temp23_before6[,cc]))) + 
      geom_point() + labs(title=col) + scale_colour_discrete(name=cc) 

enter image description here

+0

Можете ли вы вкратце объяснить, что «aes_string» делает по-другому, что заставляет его «помнить», какие были назначения цвета? Только для моей собственной информации. – brittenb

+2

@brittenb позволяет стандартную оценку в отличие от интерактивного режима NSE. Вот еще https://nsaunders.wordpress.com/2013/02/26/rggplot2-tip-aes_string/ –

0

Я думаю, проблема заключается в том, как ggplot ссылается на свои цвета при печати графика. Я не совсем уверен в этом, но давайте посмотрим на пример.

temp23_before6 <- data.frame(TIME = c(1, 2, 3, 4, 5), 
          VALUE = c(1, 2, 3, 4, 5), 
          P = c(1, 2, 3, 2, 1), 
          D = c(4, 5, 6, 7, 8)) 
i <- 1 
p <- list() 
for (column in names(temp23_before6)) { 
    l <-length(unique(temp23_before6[, column])) 
    if (l < 20 && l > 1) { 
    colors <- factor(temp23_before6[, column]) 
    print(colors) 
    p[[i]] <- ggplot(temp23_before6, aes(TIME, VALUE, colour=colors)) + 
     geom_point() + labs(title=column) 

    i <- i + 1 
    } 
} 

plot(p[[1]]) 

В примере, вы увидите, что я удалил назначение column к cc, поскольку нам не нужно, что и я явно установить переменную цвет, который будет использоваться. Если мы запустим вышеприведенный код, все будет работать без ошибок, но, как отметил OP, каждый график является точным. Кроме того, мы замечаем, что уровни факторов цвета одинаковы на всех графиках и равны уровням факторов последней итерации. Это заставило меня задуматься о том, как ggplot присваивает цвета. Итак, давайте изменим colors, чтобы быть чем-то другим и повторить сюжет, который уже сгенерирован.

colors <- factor(20:30) 
plot[[p1]] 

Это дает нам ошибку, сообщая нам, что эстетика должна быть длиной 1 или же, как данные (5). Это, по-видимому, означает, что во время построения графика данные, используемые для назначения цветов, рисуются в это время и не «сохраняются». Итак, когда вы запустите свою функцию multiplot, все графики рисуют из одних и тех же данных, чтобы назначить цвета, которые в вашем случае: temp23_before6[, column], где column теперь статично и сохраняется как последнее имя столбца.

+1

Не похоже, что 'assign' решает проблему, к сожалению. Если я создаю 5 переменных, я все же должен установить цвет как 'color = get (paste0 (" colors_ ", i))' и 'i' всегда равен 5, когда я запускаю код – Archeg

+0

Да, я заметил, что когда я попытался реализовать обходное решение. В результате я удалил эту часть ответа. – brittenb