我正在使用一个大型数据框,我需要从中排除包含除少数字符之外的所有字符。
目前我正在使用以下代码这样做并且它工作正常,但我似乎只能一次将它应用于单个列,这不仅效率低,而且耗费时间,因为我有很多列通过工作。
df <- df[(df$column_name_01 %in% c("a", "b", "c", "d")),]
到目前为止,我已经尝试过像这样引用多个列(因为这种方法适用于单个列):
df <- df[(df[, 1:10] %in% c("a", "b", "c", "d")),]
但这显然不符合预期。是否有一种简洁的方法可以从包含某些字符的数据框中排除行(或者哪种方式与某些字符不匹配)?
答案 0 :(得分:0)
您可以计算是否希望10列中的每一行合并为Reduce
和"&"
的单个向量:
df[Reduce("&", lapply(df[,1:10], function(x) x %in% c("a", "b", "c", "d"))),]
# NA NA NA NA NA NA NA NA NA NA
# 14 a c a d d c d c c c
# 25 b a a a b a c a a c
# 29 d d d a a a b c c a
# 31 c b b d b c a b b c
# 33 b a c b a d c a a c
# 36 c d c b d a c a a a
# 42 b b a a b c d b d d
# 45 c c b b d a b a d b
您也可以通过将数据框转换为矩阵并使用rowSums
来确保行中的所有值都落在所需的集合中来执行此操作:
df[rowSums(matrix(unlist(df[,1:10]) %in% c("a", "b", "c", "d"), nrow(df))) == 10,]
# NA NA NA NA NA NA NA NA NA NA
# 14 a c a d d c d c c c
# 25 b a a a b a c a a c
# 29 d d d a a a b c c a
# 31 c b b d b c a b b c
# 33 b a c b a d c a a c
# 36 c d c b d a c a a a
# 42 b b a a b c d b d d
# 45 c c b b d a b a d b
这两个解决方案都应该比基于apply
的大型矩阵解决方案更快(我在这里对100k行数据帧进行基准测试)因为它们在少量列而不是大量行上运行,更好地利用矢量化:
josilber.lapply <- function(df) df[Reduce("&", lapply(df[,1:10], function(x) x %in% c("a", "b", "c", "d"))),]
josilber.rowSums <- function(df) df[rowSums(matrix(unlist(df[,1:10]) %in% c("a", "b", "c", "d"), nrow(df))) == 10,]
crimson.apply <- function(df) df[apply(df[,1:10], 1, function(x) all(x %in% c("a", "b", "c", "d"))),]
library(microbenchmark)
microbenchmark(josilber.lapply(big.df), josilber.rowSums(big.df), crimson.apply(big.df))
# Unit: milliseconds
# expr min lq mean median uq max neval
# josilber.lapply(big.df) 67.17092 71.0628 83.36787 74.74011 86.00722 231.6794 100
# josilber.rowSums(big.df) 98.75142 116.3975 136.28880 128.28851 149.55155 301.9346 100
# crimson.apply(big.df) 676.66290 725.6616 789.45954 762.74171 805.72437 2681.8203 100
数据:
set.seed(144)
df <- unname(do.call(data.frame, replicate(10, sample(letters[1:5], 50, replace=TRUE), simplify=FALSE)))
set.seed(144)
big.df <- unname(do.call(data.frame, replicate(10, sample(letters[1:5], 100000, replace=TRUE), simplify=FALSE)))
答案 1 :(得分:0)
我想你想在这里定期申请:
df[apply(df[,1:10], 1, function(x) all(x %in% c("a", "b", "c", "d"))),]
或不匹配的行
df[apply(df[,1:10], 1, function(x) all(! x %in% c("a", "b", "c", "d"))),]