【发布时间】:2017-09-21 11:27:17
【问题描述】:
我有一个包含一些逻辑列的数据集,我想用相应的列名替换“TRUE”值。我问了一个类似的问题here,并在其他 S/O 用户的一些建议的帮助下找到了合适的解决方案。但是,该解决方案不使用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
这是不正确的,因为它不是遍历每个列名称以获取替换值,而是回收第一个(在本例中为“apple”)。
此外,如果我颠倒新旧值的顺序,该函数将忽略我对第二个值的字符串替换,并在所有情况下都使用前两个列名作为替换:
# 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
我确定我可能遗漏了一些简单的东西,但有谁知道为什么该函数不遍历列名(以及如何编辑它来做到这一点)?
我的预期输出如下:
> 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。 -
谢谢 - 找不到 'Map' 的语法示例,但帮助说它是 mapply 的包装器 - 这样做
mydt[, (logicalcols) := mapply(recode.multi, datacol = .SD, oldval = c(TRUE, FALSE), newval = c(names(.SD), "FALSE"), SIMPLIFY = FALSE), .SDcols = logicalcols]几乎让我到了那里,除了 FALSE 值被转换为 NA .
标签: r replace logic data.table columnname