我们可以使用
lapply
循环遍历
df
的列'A1'和'A4',并使用
sapply
将它们与值1:12进行比较。使用
Reduce
与
|
,将
list
输出合并为单个矩阵。
+
用于将逻辑矩阵转换为二进制格式。在最后一步中,我们使用
cbind
与原始数据集结合。
cbind(df, +(Reduce('|', lapply(df[c(1,4)], function(x) sapply(1:12, '==', x)))))
另一个使用基本R而无需循环的选项是table
。我们将感兴趣的列即'A1'、'A4'进行unlist
,然后用1:12
值获取table
,对取出的矩阵进行双重否定(!!
),将'0'值转为FALSE,其他值转为TRUE,使用+
将逻辑矩阵强制转换为二进制1/0
,再与原始数据集cbind
。
subDF <- df[c('A1', 'A4')]
newdf <- cbind(df, +(!!table(rep(1:12, ncol(subDF)), unlist(subDF))))
colnames(newdf)[5:ncol(newdf)] <- paste0('V', 1:12)
newdf
我们也可以使用data.table
。不确定这是否非常高效,因为我们在data.table
内部执行了table
操作。该方法的步骤是先将“data.frame”转换为“data.table”(setDT(df)
),然后在.SDcols
中指定的列上unlist
,获取行数的seq_len
(.N
),例如示例中的1:12,通过rep
将其复制到“nm1”的长度,并获取table
。
我们从table
类创建一个data.table
(split(tbl..
),通过使用for循环遍历列,我们将值设置为二进制的0/1
。 set
方法非常高效,因为它避免了[.data.table
的开销。稍后,我们可以与原始数据集cbind
。
library(data.table)
nm1 <- c('A1', 'A4')
tbl <- setDT(df)[, table(rep(seq_len(.N),length(nm1)), unlist(.SD)), .SDcols=nm1]
dt1 <- setDT(split(tbl, col(tbl)))[]
for(j in seq_along(dt1)) {
set(dt1, i=NULL, j=j, value=+(!!dt1[[j]]))
}
cbind(df, dt1)
cbind(df, +(sapply(1:12, function(i) i==df['A1']|i==df['A4'])))
- akrun