我有一个包含一些逻辑列的数据集,并且希望用相应的列名称替换“TRUE”的值。我问了一个类似的问题here,并且能够借助其他S/O用户的一些建议来确定合适的解决方案。但是,该解决方案不使用data.table语法,而是复制整个数据集而不是按引用进行替换,这非常耗时。R使用data.table语法将逻辑列中的正值替换为列名称
什么是使用data.table语法来做到这一点的最合适的方法?
我尝试这样做:
# Load library
library(data.table)
# Create dummy data.table:
mydt <- data.table(id = c(1,2,3,4,5),
ptname = c("jack", "jill", "jo", "frankie", "claire"),
sex = c("m", "f", "f", "m", "f"), apple = c(T,F,F,T,T),
orange = c(F,T,F,T,F),
pear = c(T,T,T,T,F))
# View dummy data:
> mydt
id ptname sex apple orange pear
1: 1 jack m TRUE FALSE TRUE
2: 2 jill f FALSE TRUE TRUE
3: 3 jo f FALSE FALSE TRUE
4: 4 frankie m TRUE TRUE TRUE
5: 5 claire f TRUE FALSE FALSE
# Function to recode values in a data.table:
recode.multi <- function(datacol, oldval, newval) {
trans <- setNames(newval, oldval)
trans[ match(datacol, names(trans)) ]
}
# Get a list of all the logical columns in the data set:
logicalcols <- names(which(mydt[, sapply(mydt, is.logical)] == TRUE))
# Apply the function to convert 'TRUE' to the relevant column names:
mydt[, (logicalcols) := lapply(.SD, recode.multi,
oldval = c(FALSE, TRUE),
newval = c("FALSE", names(.SD))), .SDcols = logicalcols]
# View the result:
> mydt
id ptname sex apple orange pear
1: 1 jack m apple FALSE apple
2: 2 jill f FALSE apple apple
3: 3 jo f FALSE FALSE apple
4: 4 frankie m apple apple apple
5: 5 claire f apple FALSE FALSE
这是不正确的作为,而不是通过对替换值每列名迭代,它只是回收的第一个(在这种情况下,“苹果”)。
而且,如果我扭转新旧值的顺序,函数忽略我的字符串替换为第二个值,并使用了前两个列名作为替代品在所有情况下:
# Apply the function with order of old and new values reversed:
mydt[, (logicalcols) := lapply(.SD, recode.multi,
oldval = c(TRUE, FALSE),
newval = c(names(.SD), "FALSE")), .SDcols = logicalcols]
# View the result:
> mydt
id ptname sex apple orange pear
1: 1 jack m apple orange apple
2: 2 jill f orange apple apple
3: 3 jo f orange orange apple
4: 4 frankie m apple apple apple
5: 5 claire f apple orange orange
我m确定我可能错过了一些简单的东西,但有人知道为什么函数不会遍历列名(以及如何编辑它来做到这一点)?
我的预期产出将如下所示:
> mydt
id ptname sex apple orange pear
1: 1 jack m apple FALSE pear
2: 2 jill f FALSE orange pear
3: 3 jo f FALSE FALSE pear
4: 4 frankie m apple orange pear
5: 5 claire f apple FALSE FALSE
或者简洁data.table语法的任何其他建议,以实现这一目标将非常感激。
使用字符,而不是逻辑将在以后的任何分析我想是痛苦的。关于你的方式不起作用的原因,'lapply'一次迭代一件事(这里的.SD)。如果您需要它遍历.SD和名称(.SD),请尝试使用Map。 – Frank
谢谢 - 找不到'地图'的语法示例,但帮助说它是一个适用于mapply的包装 - 这样做'mydt [,(logicalcols):= mapply(recode.multi, datacol = .SD, oldval = c(TRUE,FALSE), newval = c(names(.SD),“FALSE”), SIMPLIFY = FALSE)。SDcols = logicalcols] '除了将FALSE值转换为NAs之外,几乎可以让我在那里。 –