2012-01-15 48 views
4

我想寫一個函數,它需要一個數據框的名稱保存時間序列數據和該數據框中列的名稱作爲參數。該函數對該數據執行各種操作,其中之一是在列中添加每年的運行總計。我正在使用plyr。如何使用變量名稱來引用具有ddply的數據幀列?

當我使用直接與ddply和cumsum列的名字,我沒有問題:

require(plyr) 
df <- data.frame(date = seq(as.Date("2007/1/1"), 
        by = "month", 
        length.out = 60), 
       sales = runif(60, min = 700, max = 1200)) 

df$year <- as.numeric(format(as.Date(df$date), format="%Y")) 
df <- ddply(df, .(year), transform, 
      cum_sales = (cumsum(as.numeric(sales)))) 

這是一個好主意,但最終目的是能夠列名傳遞給該功能。當我嘗試在地方列名的使用變量,如我所料不工作:

mycol <- "sales" 
df[mycol] 

df <- ddply(df, .(year), transform, 
      cum_value2 = cumsum(as.numeric(df[mycol]))) 

我想我知道如何按名稱訪問列。這讓我很擔心,因爲這表明我沒有理解關於索引和提取的基本知識。我原以爲這種以名稱來引用列是一種常見的需要。

我有兩個問題。

  1. 我在做什麼錯誤,即我誤解了什麼?
  2. 有沒有更好的方法來解決這個問題,記住列的名字事先不會被函數知道?

TIA

回答

7

ddply的參數是在原始數據框分成的每個部分的上下文中評估的表達式。你的df [myval]解決了整個數據框,所以你不能按原樣傳遞它(爲什麼你需要那些as.numeric(as.character())的東西 - 它們完全沒用)。

最簡單的方法是編寫自己的函數,它可以完成一切,並將列名傳遞給下方。

df <- ddply(df, 
      .(year), 
      .fun = function(x, colname) transform(x, cum_sales = cumsum(x[,colname])), 
      colname = "sales") 
+0

它適合我。有用的例子,謝謝。 – SlowLearner 2012-01-15 14:44:51

1

的問題是,ddply預計其最後的參數是表達式,這將在data.frame的塊進行評估(每年,在你的例子)。 如果使用df[myval],則表示整個data.frame,而不是每年的塊。

下面的工作,但不是很優雅:我建立表達式作爲一個字符串,然後將其轉換爲eval(parse(...))

ddply(df, .(year), transform, 
    cum_value2 = eval(parse(text = 
    sprintf("cumsum(as.numeric(as.character(%s)))", mycol) 
)) 
) 
+0

謝謝文森特 - 我實際上嘗試了eval和parse的組合,但卻弄錯了語法。這清除了我。乾杯,丹 – SlowLearner 2012-01-15 14:44:22

相關問題