我有一個包含一些邏輯列的數據集,並且希望用相應的列名稱替換「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之外,幾乎可以讓我在那裏。 –