2012-05-21 4 views
3

У меня есть функция, которая принимает фрейм данных и отображает несколько столбцов из этого фрейма данных с помощью ggplot2. Функция aes() в ggplot2 принимает аргумент метки, и я хочу использовать sprintf для форматирования этого аргумента - и это то, что я делал много раз раньше в другом коде. Когда я передаю строку формата sprintf (в данном случае «% 1.1f»), она говорит «объект не найден». Если я использую функцию round() и передаю аргумент этой функции, он может найти ее без проблем. То же самое касается формата(). По-видимому, только sprintf() не может видеть объект.R: round() может найти объект, sprintf() не может, почему?

Сначала я думал, что это была ленивая проблема оценки, вызванная вызовом функции, а не с использованием встроенного кода, но с использованием force() в строке формата, которую я передаю в sprintf, не решает проблему. Я могу обойти это, но я хотел бы знать, почему это происходит. Конечно, это может быть что-то тривиальное, что я забыл.

В. Почему sprintf() не находит строковый объект?

код следующим образом (отредактированный и обрезают для более минимального примера)

require(gdata) 
require(ggplot2) 
require(scales) 
require(gridExtra) 
require(lubridate) 
require(plyr) 
require(reshape) 

set.seed(12345) 
# Create dummy time series data with year and month 
monthsback <- 64 
startdate <- as.Date(paste(year(now()),month(now()),"1",sep = "-")) - months(monthsback) 
mydf <- data.frame(mydate = seq(as.Date(startdate), by = "month", length.out = monthsback), myvalue5 = runif(monthsback, min = 200, max = 300)) 
mydf$year <- as.numeric(format(as.Date(mydf$mydate), format="%Y")) 
mydf$month <- as.numeric(format(as.Date(mydf$mydate), format="%m")) 

getchart_highlight_value <- function(
          plotdf, 
          digits_used = 1 
         ) 
{ 
    force(digits_used) 
    #p <- ggplot(data = plotdf, aes(x = month(mydate, label = TRUE), y = year(mydate), fill = myvalue5, label = round(myvalue5, digits_used))) + 
    # note that the line below using sprintf() does not work, whereas the line above using round() is fine 
    p <- ggplot(data = plotdf, aes(x = month(mydate, label = TRUE), y = year(mydate), fill = myvalue5, label = sprintf(paste("%1.",digits_used,"f", sep = ""), myvalue5))) + 
     scale_x_date(labels = date_format("%Y"), breaks = date_breaks("years")) + 
     scale_y_reverse(breaks = 2007:2012, labels = 2007:2012, expand = c(0,0)) + 
     geom_tile() + geom_text(size = 4, colour = "black") + 
     scale_fill_gradient2(low = "blue", high = "red", limits = c(min(plotdf$myvalue5), max(plotdf$myvalue5)), midpoint = median(plotdf$myvalue5)) + 
     scale_x_discrete(expand = c(0,0)) + 
     opts(panel.grid.major = theme_blank()) + 
     opts(panel.background = theme_rect(fill = "transparent", colour = NA)) + 
     png(filename = "c:/sprintf_test.png", width = 700, height = 300, units = "px", res = NA) 
     print(p) 
     dev.off() 
} 

getchart_highlight_value (plotdf <- mydf, 
          digits_used <- 1) 
+3

вы можете сделать это минимальный пример? – baptiste

+0

Ваш код не запускается в R 2.15. Я получаю «Ошибка в get (x, envir = this, inherits = inh) (это, ...): неиспользуемый аргумент (метки) (метки = функция (x) формат (х, формат), breaks = function (x) fullseq (x, width)) ' –

+0

Спасибо @baptiste и Joris, рассмотрим обе проблемы как можно скорее. – SlowLearner

ответ

4

Используя минимальный пример Мартина (то есть минимальный пример, смотри также this question), вы можете сделать код работы, указав среды ggplot() следует использовать. Для этого укажите аргумент environment в функции ggplot(), например, так:

require(ggplot2) 

getchart_highlight_value <- function(df) 
{ 
    fmt <- "%1.1f" 
    ggplot(df, aes(x, x, label=sprintf(fmt, lbl)), 
     environment = environment()) + 

    geom_tile(bg="white") + 
    geom_text(size = 4, colour = "black") 
} 

df <- data.frame(x = 1:5, lbl = runif(5)) 
getchart_highlight_value (df) 

Функция environment() возвращает текущую (локальную) среду, которая является средой, созданной с помощью функции getchart_highlight_value(). Если вы не укажете это, ggplot() будет выглядеть в глобальной среде, и там переменная fmt не определена.

Ничего общего с ленивой оценкой, все зависит от выбора правильной среды.

Код выше производит следующий сюжет:

enter image description here

+0

+1 Для обеспечения ответа, но я думаю, что это только половина объяснения. AFAIK, вызов 'ggplot' или' geom _...' оценивает все аргументы в 'aes()' в среде DataFrame данных, а не глобально. Вот почему он терпит неудачу. – Andrie

+0

@Andrie - Я только что проверил с «производственной версией» кода, а не с минимальным примером, и добавление среды = environment() разрешает проблему sprintf(), которая не может найти эту переменную. Согласуется ли это с вашим тезисом? – SlowLearner

+0

@Andrie Значение по умолчанию для среды в ggplot.data.frame является globalenv(). –

4

Вот пример

require(ggplot2) 

getchart_highlight_value <- function(df) 
{ 
    fmt <- "%1.1f" 
    ggplot(df, aes(x, x, label=sprintf(fmt, lbl))) + geom_tile() 
} 

df <- data.frame(x = 1:5, lbl = runif(5)) 
getchart_highlight_value (df) 

минимально-эр Это терпит неудачу с

> getchart_highlight_value (df) 
Error in sprintf(fmt, lbl) : object 'fmt' not found 

Если я создаю fmt в глобальная среда, тогда все в порядке; возможно, это объясняет комментарии «иногда это работает»/«это работает для меня» выше.

> sessionInfo() 
R version 2.15.0 Patched (2012-05-01 r59304) 
Platform: x86_64-unknown-linux-gnu (64-bit) 

locale: 
[1] LC_CTYPE=en_US.UTF-8  LC_NUMERIC=C    
[3] LC_TIME=en_US.UTF-8  LC_COLLATE=en_US.UTF-8  
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 
[7] LC_PAPER=C     LC_NAME=C     
[9] LC_ADDRESS=C    LC_TELEPHONE=C    
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C  

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

other attached packages: 
[1] ggplot2_0.9.1 

loaded via a namespace (and not attached): 
[1] colorspace_1.1-1 dichromat_1.2-4 digest_0.5.2  grid_2.15.0  
[5] labeling_0.1  MASS_7.3-18  memoise_0.1  munsell_0.3  
[9] plyr_1.7.1   proto_0.3-9.2  RColorBrewer_1.0-5 reshape2_1.2.1  
[13] scales_0.2.1  stringr_0.6  
+0

Как раз округлить вещи: можете ли вы подтвердить, что используете последние ggplot2 и R2.15? И пока мы это делаем - может ли кто-нибудь проверить, что эквивалент 'label = sprintf (fmt, lbl)' внутри какой-либо другой функции или пакета работает правильно? –

+0

@CarlWitthoft - Мартин или я? Я на ggplot2 0.9.1 и 2.15. – SlowLearner