我正在尝试编写一个函数,它将获取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上发现了将字符串转换为变量名的几个线程,但是我找不到任何以这种方式使用的线程,其中变量必须随后引用并以非交互方式分配值。
感谢您的帮助。
答案 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=".")