我有一個大約有一個 data.table x。2M 行和 2 列:entry和code. entry包含可能entry在其他地方以降低形式重復的字符值。此外,存在所有低級條目,它們沒有非低級形式。中的每一行在列中x都有一個唯一的代碼code。我創建了一個只有 6 行的可重現示例。
library(data.table)
x <- data.table(entry = c("Aaa", "Bbb", "Ccc", "aaa", "bbb", "ddd"),
code = c(1, 2, 3, 4, 5, 6))
x
entry code
1: Aaa 1
2: Bbb 2
3: Ccc 3
4: aaa 4
5: bbb 5
6: ddd 6
如您所見,Aaa并且Bbb還帶有降低的“對應物”aaa和bbb. Ccc沒有降級形式,ddd也沒有非降級形式。
我現在想分配一個新列,該列low_code包含降低的對應項的代碼(如果有的話)。如果沒有,代碼應該保持不變。這就是我在此示例中的目標:
entry code low_code
1: Aaa 1 4
2: Bbb 2 5
3: Ccc 3 3
4: aaa 4 4
5: bbb 5 5
6: ddd 6 6
如您所見, 和 的代碼被分配給aaa和。對于,沒有降低版本,所以代碼保持不變。bbbAaaBbbCcc
到目前為止,我所做的是(并且有效):
x$low_code <- sapply(x$entry, USE.NAMES = F, FUN = function (e) {
low_e <- tolower(e)
ret <- x[x$entry == low_e,][["code"]]
if (length(ret) == 0) { # If no low entry is found...
ret <- x[x$entry == e,][["code"]] # ...return original code
}
stopifnot(length(ret) %in% c(0, 1)) # Too many return values (should never happen)
ret
})
但是,對于超過 200 萬行的原始 data.table,它非常慢。我懷疑這是由于每個條目的索引(e在上面的代碼中)。
如果沒有更快的選項(也許利用 data.table 語法),我會感到非常驚訝,但我沒有想法。非常感謝任何幫助 - 如果您有時間,還請用幾句話解釋您的解決方案,以便我從中學習。與往常一樣,我希望我沒有忽略任何解決類似問題的答案。太感謝了!
uj5u.com熱心網友回復:
下面的呢?
rows = grep("^[A-Z]", x$entry)
x[(rows), lentry := tolower(entry)]
x[(rows), low_code := x[(-rows)][.SD, on = .(entry = lentry), x.code]]
rm(rows)
x[, lentry := NULL]
x[is.na(low_code), low_code := code]
# entry code low_code
# <char> <num> <num>
# 1: Aaa 1 4
# 2: Bbb 2 5
# 3: Ccc 3 3
# 4: aaa 4 4
# 5: bbb 5 5
# 6: ddd 6 6
uj5u.com熱心網友回復:
library(data.table)
x <- data.table(entry = c("Aaa", "Bbb", "Ccc", "aaa", "bbb", "ddd"), code = c(1, 2, 3, 4, 5, 6))
x[, low_entry := tolower(entry)
][entry == low_entry, low_entry := NA]
x[x, low_code := i.code, on = .(low_entry == entry)
][, low_entry := NULL
][, low_code := fcoalesce(low_code, code)]
x
# entry code low_code
# <char> <num> <num>
# 1: Aaa 1 4
# 2: Bbb 2 5
# 3: Ccc 3 3
# 4: aaa 4 4
# 5: bbb 5 5
# 6: ddd 6 6
即使有多個較低的entry值,這也應該有效。例如,
x <- data.table(entry = c("Aaa", "Bbb", "Ccc", "aaa", "bbb", "ddd", "aaa"), code = c(1, 2, 3, 4, 5, 6, 7))
x[, low_entry := tolower(entry)
][entry == low_entry, low_entry := NA]
x[x, low_code := i.code, on = .(low_entry == entry)
][, low_entry := NULL
][, low_code := fcoalesce(low_code, code)]
x
# entry code low_code
# <char> <num> <num>
# 1: Aaa 1 7 # <-- reflects the _last_ `"aaa"` found
# 2: Bbb 2 5
# 3: Ccc 3 3
# 4: aaa 4 4 # <-- own `code`
# 5: bbb 5 5
# 6: ddd 6 6
# 7: aaa 7 7 # <-- own `code`
uj5u.com熱心網友回復:
將完整資料集與所有小寫子集合并,不匹配的 NA 將使用現有代碼進行更新:
merge(x[, .(rn = 1:.N, entry_low = tolower(entry), entry, code) ],
x[ tolower(entry) == entry, .(entry_low = entry, code_low = code)],
by = "entry_low", all.x = TRUE
)[ is.na(code_low), code_low := code
][ order(rn), .(entry, code, code_low)]
# entry code code_low
# 1: Aaa 1 4
# 2: Bbb 2 5
# 3: Ccc 3 3
# 4: aaa 4 4
# 5: bbb 5 5
# 6: ddd 6 6
uj5u.com熱心網友回復:
如果您想保持原始 data.table 不變,這可能會有所幫助。
- 首先生成
tolower分組條目, - 然后選擇相應的代碼值和
NA如果未找到分組,則最后放置值的代碼。
x[, .(code, entry, l_entry = tolower(entry))
][, .(entry, l = last(code[l_entry == entry]), code), by = l_entry
][, .(entry, code, low_code = ifelse(is.na(l), code, l))]
entry code low_code
1: Aaa 1 4
2: aaa 4 4
3: Bbb 2 5
4: bbb 5 5
5: Ccc 3 3
6: ddd 6 6
如果存在更多具有不同值的較低條目(例如aaalast ),則采用該條目。也可以改成first。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/529909.html
標籤:r数据表
下一篇:在R中選擇值在 /-1范圍內的行
