R:循环遍历data.frame中的变量名列表以创建新变量

时间:2015-05-28 23:40:27

标签: r

我正在尝试编写一个函数,它将获取data.frame,data.frame的变量名称的列表(或字符向量),并创建一些新的变量,其名称派生自列表中相应的变量名称以及列表中指定的变量的值。

例如,如果data.frame d具有变量x,y,z,w,则名称列表为c('x','z'),输出可能是名称为x.cat,z.cat和基于d $ x和d $ z的值的值。

我可以用循环

来做到这一点
df <- data.frame(x = c(1 : 10), y = c(11 : 20), z = c(21 : 30), w = c(41: 50))  

vnames <- c("x", "w")

loopfunc <- function(dat, vlst){
  s <- paste(vlst, "cat", sep = ".")
  for (i in 1:length(vlst)){
  dat[s[i]] <- NA
  dat[s[i]][dat[vlst[i]] %% 4 == 0 ] <- 0
  dat[s[i]][dat[vlst[i]] %% 4 == 1 | dat[vlst[i]] %%4 == 3] <- 1
  dat[s[i]][dat[vlst[i]] %% 4 == 2 ] <- 2
 }
  dat[s]
}
dout <- loopfunc(df, vnames)

这将输出一个10x2 data.frame,列x.cat和w.cat,这些值的值为0,1或2,具体取决于df $ x和df $ w mod 4的相应值的余数

我想找到一种没有循环的方法,也许使用apply函数?

这是尝试失败

noloopfunc <- function(dat, l){
  assign(l[2], NA)
  assign(l[2][d[l[1]] %% 4 == 0], 0)
  assign(l[2][d[l[1]] %% 4 == 2], 2)
  assign(l[2][(d[l[1]] %% 4 == 1) | (d[l[1]] %% 4 == 3)], 1)
  as.name(l[2])
}

newvnames <- sapply(vnames, function(x){paste(x, "cat", sep = ".")})
vpairs <- mapply(c, vnames, newvnames, SIMPLIFY = F)

lapply(vpairs, noloopfunc, d <- df)

这里形式论证l应该代表vpairs [[1]]或vpairs [[2]],两个字符串向量都是长度为2。

我在Stackoverflow上发现了将字符串转换为变量名的几个线程,但是我找不到任何以这种方式使用的线程,其中变量必须随后引用并以非交互方式分配值。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您可以使用apply变体替换您的循环

dout <- as.data.frame(sapply(vnames, function(x) {
    out <- rep(NA, nrow(df))
    out[df[,x] %% 4 == 0] <- 0
    out[df[,x] %% 4 == 1 | df[,x] %% 4 == 3] <- 1
    out[df[,x] %% 4 == 2] <- 2
    out
}))
names(dout) <- paste(vnames, "cat", sep=".")