我有一个> 1M行长的字符串数据框:
>head(df)
A B C D
1 S1 S2 U1 U2
2 S1 S2 S2 S1
3 S2 S1 S1 S2
4 S1 M2 U1 S2
5 S1 S1 M2 M1
6 M2 M2 M1 M2
Run Code Online (Sandbox Code Playgroud)
我想确定存在特定字符的所有行(例如,“U”)。到目前为止,我发现的解决方案是有效的,但它们非常慢,例如:
matches <- apply(as.matrix(df), 1, function(x){ sum(grepl("U", x, perl=T)) > 0 })
Run Code Online (Sandbox Code Playgroud)
知道如何改进这个查询吗?谢谢!
编辑:更新地址评论:
以下也非常快(0.31 秒,甚至比以前更快):
rows <- which(
rowSums(
`dim<-`(grepl("U", as.matrix(df), fixed=TRUE), dim(df))
) > 0
)
Run Code Online (Sandbox Code Playgroud)
并产生与先前答案相同的结果。使用fixed=FALSE大约两倍的时间,但您的示例不需要这样做。
我们在这里所做的是通过应用grepl到矩阵来作弊,尽管我们真正关心的是df变成向量(矩阵就是这样),这as.matrix是实现此目的的更快方法之一。然后我们可以只运行一个grepl命令。最后,我们dim<-将grepl向量结果转回矩阵,并用于rowSums检查哪些行匹配。
以下是这比您的版本快得多的原因:
grepl一次,而不是像您那样调用一百万次,apply因为函数apply适用于每行调用一次;grepl是矢量化的,这意味着您希望尽量减少调用它的次数并利用矢量化rowSums而不是进行行匹配计数apply;rowSums是一个更快的版本apply(x, 1, sum)(请参阅 文档?rowSums)。以前的答案:
这是一个相对简单的解决方案,它在我的系统上运行 0.35 秒,用于 1MM 行 x 4 列数据帧:
rows <- which(rowSums(as.matrix(df) == "U") > 0)
Run Code Online (Sandbox Code Playgroud)
确认
df[head(rows), ]
Run Code Online (Sandbox Code Playgroud)
产生(每一行都有一个 U):
a b c d
5 F B D U
8 R S U F
15 U L R P
20 U E E O
21 Y U D I
32 P F U H
Run Code Online (Sandbox Code Playgroud)
和数据:
set.seed(1)
df <- as.data.frame(
`names<-`(
replicate(4, sample(LETTERS, 1e6, rep=T), simplify=F),
letters[1:4]
)
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4280 次 |
| 最近记录: |