我有下表:
FN LN LN1 LN2 LN3 LN4 LN5
a b b x x x x
a c b d e NA NA
a d c a b x x
a e b c d x e
我正在过滤 LN1 至 LN5 中存在 LN 的记录。
我使用的代码:
testFilter = filter(test, LN %in% c(LN1, LN2, LN3, LN4, LN5))
结果不是我所期望的:
ï..FN LN LN1 LN2 LN3 LN4 LN5
1 a b b x x x x
2 a c b d e <NA> <NA>
3 a d c a b x x
4 a e b c d x e
据我所知,c(LN1, LN2, LN3, LN4, LN5)
给出:"b""b""c""b""x""d""a ""c""x""e""b""d""x"NA "x""x""x"NA "x""e"
并且知道这就是错误所在。
理想情况下,我只想返回第一条和第四条记录。
FN LN LN1 LN2 LN3 LN4 LN5
a b b x x x x
a e b c d x e
我想仅使用列名称来过滤它们。这只是 540 万条记录的子集。
最佳答案
还有一种使用 data.table
和 Reduce()
的替代方法:
library(data.table)
cols <- paste0("LN", 1:5)
setDT(test)[test[, .I[Reduce(`|`, lapply(.SD, function(x) !is.na(x) & LN == x))],
.SDcols = cols]]
FN LN LN1 LN2 LN3 LN4 LN5 1: a b b x x x x 2: a e b c d x e
数据
library(data.table)
test <- fread(
"FN LN LN1 LN2 LN3 LN4 LN5
a b b x x x x
a c b d e NA NA
a d c a b x x
a e b c d x e")
基准
library(data.table)
library(dplyr)
n_row <- 1e6L
set.seed(123L)
DT <- data.table(
FN = "a",
LN = sample(letters, n_row, TRUE))
cols <- paste0("LN", 1:5)
DT[, (cols) := lapply(1:5, function(x) sample(c(letters, NA), n_row, TRUE))]
DT
df1 <- as.data.frame(DT)
bm <- microbenchmark::microbenchmark(
zx8754 = {
df1[ apply(df1, 1, function(i) i[2] %in% i[3:7]), ]
},
eric = {
df1[ which(df1$LN == df1$LN1 |
df1$LN == df1$LN2 |
df1$LN == df1$LN3 |
df1$LN == df1$LN4 |
df1$LN == df1$LN5), ]
},
uwe = {
DT[DT[, .I[Reduce(`|`, lapply(.SD, function(x) !is.na(x) & LN == x))],
.SDcols = cols]]
},
axe = {
filter_at(df1, vars(num_range("LN", 1:5)), any_vars(. == LN))
},
jaap = {df1[!!rowSums(df1$LN == df1[, 3:7], na.rm = TRUE),]},
times = 50L
)
print(bm, "ms")
Unit: milliseconds expr min lq mean median uq max neval cld zx8754 3120.68925 3330.12289 3508.03001 3460.83459 3589.10255 4552.9070 50 c eric 69.74435 79.11995 101.80188 83.78996 98.24054 309.3864 50 a uwe 93.26621 115.30266 130.91483 121.64281 131.75704 292.8094 50 a axe 69.82137 79.54149 96.70102 81.98631 95.77107 315.3111 50 a jaap 362.39318 489.86989 543.39510 544.13079 570.10874 1110.1317 50 b
对于 1 M 行,硬编码子集设置最快,其次是 data.table
/Reduce()
和 dplyr
/filter_at
方法。使用 apply()
速度慢 60 倍。
ggplot(bm, aes(expr, time)) + geom_violin() + scale_y_log10() + stat_summary(fun.data = mean_cl_boot)
关于r - 按列过滤数据集中的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48336563/