例如: 我有一个名为table的数据框:
Cn c1 c2 c3 c4
c3 1 3 5 6
c2 4 6 7 9
我想创建一个新列,其值包含在列中,列名在Cn中,因此它看起来像:
Cn c1 c2 c3 c4 NewCol
c3 1 3 5 6 5
c2 4 6 7 9 6
我的尝试是table$NewCol<-table[,table$Cn]
但是,table$NewCol[1]
不是每行返回1个值,而是包含(5,3)的向量,它引用Cn列中的(c3,c2),这意味着对于每一行,所有查找Cn行并将其放入新变量中。
我知道我可以使用循环但是我处理的是700万+记录数据帧,并且循环非常慢。
任何人都有任何想法如何解决这个问题?
答案 0 :(得分:3)
使用mapply
在每行和d $ Cn移动时应用[.data.frame
。
table$NewCol <- mapply(i = seq_along(d[['Cn']]),
j= d[['Cn']],
FUN = function(i,j,x) x[i,j,drop=TRUE],
MoreArgs=list(x=d))
如果要考虑速度和效率,请使用data.table
和set
(此循环 效率)
library(data.table)
setDT(d)
for(i in seq_len(nrow(d))){
set(d,j='newCol', i=i, value= d[[d[['Cn']][i]]][i])
}
答案 1 :(得分:2)
使用所需行和列值的矩阵索引进行提取。
我使用dat
作为您的data.frame名称。
dat[-1][cbind(seq_along(dat$Cn),match(as.character(dat$Cn),names(dat[-1])))]
#[1] 5 6
如:
sel <- cbind(seq_along(dat$Cn),match(as.character(dat$Cn),names(dat[-1])))
sel
# row col
# [,1] [,2]
#[1,] 1 3
#[2,] 2 2
dat[-1][sel]
#[1] 5 6
7M行的时间和4列示例约为0.4秒。
dat2 <- dat[sample(1:2,7e6,replace=TRUE),]
nrow(dat2)
#[1] 7000000
system.time({
sel <- cbind(seq_along(dat2$Cn),match(as.character(dat2$Cn),names(dat2[-1])))
dat2$newcol <- dat2[-1][sel]
})
# user system elapsed
# 0.33 0.07 0.39