2012-01-15 46 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

相关问题