首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何向量化R strsplit?

如何向量化R strsplit?
EN

Stack Overflow用户
提问于 2010-06-16 23:14:32
回答 1查看 13.8K关注 0票数 15

在创建使用strsplit的函数时,矢量输入的行为不符合预期,需要使用sapply。这是由于strsplit生成的列表输出所致。有没有一种方法可以向量化这个过程--也就是说,函数为输入的每个元素在列表中生成正确的元素?

例如,要计算字符向量中单词的长度:

代码语言:javascript
复制
words <- c("a","quick","brown","fox")

> length(strsplit(words,""))
[1] 4 # The number of words (length of the list)

> length(strsplit(words,"")[[1]])
[1] 1 # The length of the first word only

> sapply(words,function (x) length(strsplit(x,"")[[1]]))
a quick brown   fox 
1     5     5     3 
# Success, but potentially very slow

理想情况下,像length(strsplit(words,"")[[.]])这样的东西,其中.被解释为输入向量的相关部分。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-06-16 23:19:33

通常,您应该首先尝试使用矢量化函数。使用strsplit通常需要在之后进行某种迭代(这会更慢),所以如果可能的话,尽量避免它。在您的示例中,您应该改用nchar

代码语言:javascript
复制
> nchar(words)
[1] 1 5 5 3

更广泛地说,利用strsplit返回列表并使用lapply这一事实

代码语言:javascript
复制
> as.numeric(lapply(strsplit(words,""), length))
[1] 1 5 5 3

或者使用plyr中的l*ply系列函数。例如:

代码语言:javascript
复制
> laply(strsplit(words,""), length)
[1] 1 5 5 3

编辑:

为了纪念,我决定使用乔伊斯的“尤利西斯”来测试这些方法的性能:

代码语言:javascript
复制
joyce <- readLines("http://www.gutenberg.org/files/4300/4300-8.txt")
joyce <- unlist(strsplit(joyce, " "))

现在我有了所有的单词,我们可以进行计数了:

代码语言:javascript
复制
> # original version
> system.time(print(summary(sapply(joyce, function (x) length(strsplit(x,"")[[1]])))))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   3.000   4.000   4.666   6.000  69.000 
   user  system elapsed 
   2.65    0.03    2.73 
> # vectorized function
> system.time(print(summary(nchar(joyce))))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   3.000   4.000   4.666   6.000  69.000 
   user  system elapsed 
   0.05    0.00    0.04 
> # with lapply
> system.time(print(summary(as.numeric(lapply(strsplit(joyce,""), length)))))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   3.000   4.000   4.666   6.000  69.000 
   user  system elapsed 
    0.8     0.0     0.8 
> # with laply (from plyr)
> system.time(print(summary(laply(strsplit(joyce,""), length))))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   3.000   4.000   4.666   6.000  69.000 
   user  system elapsed 
  17.20    0.05   17.30
> # with ldply (from plyr)
> system.time(print(summary(ldply(strsplit(joyce,""), length))))
       V1        
 Min.   : 0.000  
 1st Qu.: 3.000  
 Median : 4.000  
 Mean   : 4.666  
 3rd Qu.: 6.000  
 Max.   :69.000  
   user  system elapsed 
   7.97    0.00    8.03 

矢量化的函数和lapply比原始的sapply版本快得多。所有解决方案都返回相同的答案(如摘要输出所示)。

显然,最新版本的plyr速度更快(使用的是稍微老一点的版本)。

票数 21
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3054612

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档