在下面的例子df中,对于每一行,我想确定b1:b3中的任何值是否在a1:a3中。如果未找到匹配项,则将不匹配的b1:b3值更改为NA。请注意,df中a和b列的数量可能会有所不同,但命名约定保持不变:
df <- structure(list(row = c(1L, 12L, 17L, 44L, 55L, 90L),
b1 = c(55L,17L, 12L, 12L, 1L, 12L),
b2 = c(NA, 44L, 44L, 17L, NA, 17L),
b3 = c(NA, 90L, 90L, 90L, NA, 44L),
a1 = c(55L, 17L, 12L, 12L, 1L, 12L),
a2 = c(NA, 44L, 44L, 17L, NA, 28L),
a3 = c(NA, 90L, NA, 90L, NA, 44L)),
row.names = c(NA, -6L),
class = "data.frame")
所需输出:
row b1 b2 b3 a1 a2 a3
1 1 55 NA NA 55 NA NA
2 12 17 44 90 17 44 90
3 17 12 44 NA 12 44 NA
4 44 12 17 90 12 17 90
5 55 1 NA NA 1 NA NA
6 90 12 NA 44 12 28 44
我可以用下面的for循环实现所需的输出:
acols <- grep("^a", colnames(df))
bcols <- grep("^b", colnames(df))
for(i in 1:nrow(df)) {
for(j in bcols) {
if(df[i, j] %in% df[i, acols]) {
next
} else {
df[i, j] <- NA
}
}
}
但我正在寻找一种更有效的方法,因为真实的数据要大得多。tidyverse
或base R是否有替代方案?我已经搜索了across()
方法,但我无法翻译任何解决方案来满足我的需求。
2条答案
按热度按时间pxiryf3j1#
这里有一个基本的解决方案,应该是相当快的:
我将你的数据扩展到50万行,在这个数据集上,这种方法的运行速度提高了50倍,只使用了1/50的内存。我怀疑随着列数的增加,差异会更大。
bkhjykvo2#
如果需要检查任何位置的值,可以对数据进行往返透视:
如果可以按列对进行检查,则可以执行以下操作: