所以让我描述一下数据:
数据
dat <- data.frame( abc1=c(7, 0, 7),
abc2=c(5, 10, 20),
abc3=c(0, 0, 10),
abc4=c(3, 5, 19),
abc5=c(2, 2, 0),
abc6=c(2, 26, 0),
xyz1=c(0, 2, 0),
xyz2=c(1, 1, 6),
xyz3=c(8, 2, 0),
xyz4=c(6, 3, 5),
xyz5=c(9, 2, 2),
xyz6=c(4, 0, 0),
hit=c(3, 4, 4))
我需要做的是在命中前后找到abc和xyz。下面的for循环非常适合小型数据集,但是如果数据超过10万行,则循环似乎永远运行。
for (c in c('abc','xyz')){
for (i in 1:nrow(dat)){
for (m in -2:2){
dat[[paste(c,'hit', m)]][i] = dat[i,paste(c, dat$hit[i]-m, sep = "")]
}
}
}
在输出文件中,第1行的'abc hit 0'表示:hit = 3,它依次从abc3中选择值并分配给abc hit 0。
abc hit -1转换为hit = 3-1 = 2,它指向abc2和xyz2
您似乎在for循环中反转了'm':它从-2到2,但是然后您得到dat$hit - m
-您想要的是减法吗?还是dat$hit + m
?
您可以执行以下操作-我尚未在大型数据集上对其进行过测试,但可以尝试一下:
dat1 <- do.call(rbind,
lapply(split(dat, 1:NROW(dat)),
function(x) {
z <- x[paste0('abc', x$hit + 2:-2)];
names(z) <- paste0('abc', -2:2);
z
}
))
split
函数为您提供数据框的行,愉快地保留列名,然后您可以在其上使用lapply
函数逐行操作。
您可以通过在hit
上加上-2到2来查找每一行的相关列。
然后您将生成的列表重新粘贴到一个数据框中。
更新:实际上,即使对于3万行,上述操作也相当慢。这样更快:
dat1 <- t(sapply(split(dat, 1:NROW(dat)),
function(x) unname(x[paste0('abc', x$hit + 2:-2)])
))
dat1 <- as.data.frame(dat1)
colnames(dat1) <- paste0('abc', -2:2)