我正在尝试编写一个函数,该函数将包含时间序列数据的数据框的名称和该数据框中列的名称作为参数。该函数对该数据执行各种操作,其中一个操作是在列中添加每年的运行总计。我正在使用plyr。
当我直接使用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])))
我以为我知道如何按名称访问列。这让我很担心,因为它表明我无法理解索引和提取的基本内容。我原本以为以这种方式按名称引用列将是一个常见的需求。
我有两个问题。
TIA
答案 0 :(得分: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")
答案 1 :(得分: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 )
))
)