动态生成未评估的表达式以创建滞后的data.frame?

时间:2011-09-28 09:55:11

标签: r eval expression plyr

我有data.frame Z,我想只选择存储在字符向量vars中的几个变量。这当然可以通过以下方式轻松完成:

Z[,vars]

问题在于我需要这些变量的lags 1 and 4。我使用lag(variable,-1)来获取它们。我尝试了之前建议的以下内容:

require(plyr)
l <- c(0,1,4)
expand.grid(x=vars,l=l)
# which results in 
  x      l
var1     0
var2     0
var3     0
var1     1
var2     1
var3     1
var1     4
var2     4
var3     4

buildFaDf <- function(x,l) paste("lag(Z$",x,",-",l,")",sep="")
test <- mlply(vars,buildFaDf)

给出一个像这样的列表:

.... 
$`4`
[1] "lag(Z$var1,-1)"

如果我调用那个列表元素我只是回到了字符,但当然我想拥有数据本身。最后,我想unlist,最后得到一个包含所有vars及其各自滞后的data.frame。

我还使用了substituteevalexpression,但无法完成。 注意我并不专注于mlply这里的解决方案,它最近刚给我看,而且我现在可能有点偏颇。

1 个答案:

答案 0 :(得分:2)

也许你的问题太复杂了。我看待它的方式,解决这个问题有两个步骤:

  • 第1步:创建data.frame的子集 - 这很简单,您可以在问题中显示。
  • 第2步:为data.frame
  • 中的所有列创建滞后变量

以下是执行第2步的一种方法。我将使用内置数据集faithful进行演示:

data(faithful)

dat <- head(faithful, 10)

lag1 <- function(x) c(NA, head(x, -1))
lag4 <- function(x) c(rep(NA, 4), head(x, -4))

data.frame(
  dat,
  llply(dat, lag1),
  llply(dat, lag4)
)

   eruptions waiting eruptions.1 waiting.1 eruptions.2 waiting.2
1      3.600      79          NA        NA          NA        NA
2      1.800      54       3.600        79          NA        NA
3      3.333      74       1.800        54          NA        NA
4      2.283      62       3.333        74          NA        NA
5      4.533      85       2.283        62       3.600        79
6      2.883      55       4.533        85       1.800        54
7      4.700      88       2.883        55       3.333        74
8      3.600      85       4.700        88       2.283        62
9      1.950      51       3.600        85       4.533        85
10     4.350      85       1.950        51       2.883        55

要将解决方案转换为执行子集化和滞后的函数,请执行以下操作:

dat <- data.frame(head(faithful, 10), newcol=LETTERS[1:10])

laggedDF <- function(x, vars){
  lag1 <- function(x) c(NA, head(x, -1))
  lag4 <- function(x) c(rep(NA, 4), head(x, -4))
  dat <- x[, vars, drop=FALSE]
  print(dat)
  data.frame(
    dat,
    llply(dat, lag1),
    llply(dat, lag4)
  )
}

laggedDF(dat, vars=c("eruptions", "newcol"))

   eruptions newcol eruptions.1 newcol.1 eruptions.2 newcol.2
1      3.600      A          NA       NA          NA       NA
2      1.800      B       3.600        1          NA       NA
3      3.333      C       1.800        2          NA       NA
4      2.283      D       3.333        3          NA       NA
5      4.533      E       2.283        4       3.600        1
6      2.883      F       4.533        5       1.800        2
7      4.700      G       2.883        6       3.333        3
8      3.600      H       4.700        7       2.283        4
9      1.950      I       3.600        8       4.533        5
10     4.350      J       1.950        9       2.883        6