3

データフレームを取得し、ggplot2を使用してそのデータフレームからいくつかの列をプロットする関数があります。ggplot2のaes()関数はlabel引数を取り、sprintfを使用してその引数をフォーマットしたいと思います。これは、他のコードでこれまで何度も行ったことです。フォーマット文字列をsprintf(この場合は「%1.1f」)に渡すと、「オブジェクトが見つかりません」と表示されます。round()関数を使用してその関数に引数を渡すと、問題なくそれを見つけることができます。format()についても同じことが言えます。どうやらsprintf()だけがオブジェクトを見ることができません。

最初は、これはコードをインラインで使用するのではなく関数を呼び出すことによって引き起こされる遅延評価の問題だと思いましたが、sprintfに渡すフォーマット文字列にforce()を使用しても問題は解決しません。私はこれを回避することができますが、なぜそれが起こるのか知りたいです。もちろん、私が見落としていたのは些細なことかもしれません。

Q. 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)
4

2 に答える 2

4

Using the minimal example of Martin (that is a minimal example, see also this question), you can make the code work by specifying the environment ggplot() should use. For that, specify the argument environment in the ggplot() function, eg like this:

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)

The function environment() returns the current (local) environment, which is the environment created by the function getchart_highlight_value(). If you don't specify this, ggplot() will look in the global environment, and there the variable fmt is not defined.

Nothing to do with lazy evaluation, everything to do with selecting the right environment.

The code above produces following plot:

enter image description here

于 2012-05-21T12:56:21.387 に答える
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       
于 2012-05-21T12:31:14.387 に答える