【问题标题】:More efficient way to create frequency column based on different groupings?基于不同分组创建频率列的更有效方法?
【发布时间】:2022-02-04 14:31:04
【问题描述】:

我有下面的代码计算每个列元素的频率(相对于它自己的列)并将所有五个频率加在一起在一列中。代码可以工作,但速度很慢,大部分处理时间都花在了这个过程上。有什么想法可以更有效地实现相同的目标吗?


Create_Freq <- function(Word_List) {

 library(dplyr)
 
 Word_List$AvgFreq <- (Word_List%>% add_count(FirstLet))[,"n"] +
                      (Word_List%>% add_count(SecLet))[,"n"] +
                      (Word_List%>% add_count(ThirdtLet))[,"n"] +
                      (Word_List%>% add_count(FourLet))[,"n"] +
                      (Word_List%>% add_count(FifthLet))[,"n"]

 return(Word_List)
}

编辑:

以提供单词列表为例

Word_List <- data.frame(Word = c("final", "first", "lover", "thing"))


Word_List$FirstLet <- substr(Word_List$Word,1,1)
Word_List$SecLet <- substr(Word_List$Word,2,2)
Word_List$ThirdtLet <- substr(Word_List$Word,3,3)
Word_List$FourLet <- substr(Word_List$Word,4,4)
Word_List$FifthLet <- substr(Word_List$Word,5,5)

}
 

对于上下文,我有另一个函数可以选择“平均”频率最高的单词。 (以前是一个平均值,但是除以 5 没用,因为它不影响最大值)

【问题讨论】:

  • 能否请您发布代码以重新生成数据?
  • 我添加了例如代码,实际代码读入了一个大约13000字的列表

标签: r performance dplyr


【解决方案1】:

这是一种可能的方法,定义一个小的辅助函数f 来访问计数列表。经过测试,它在我的机器上大约快 15 倍。

f <- function(x, tbl){
  res <- integer(5)
  for (i in seq_along(tbl)){
    res[i] <- tbl[[i]][x[i]]
  } 
  sum(res)
}  

Word_List <- data.frame(Word = c("final", "first", "lover", "thing"))
w <- unlist(Word_List, use.names = F)
m <- matrix(unlist(strsplit(w, ""), use.names = F), ncol = 4)
lookup <- apply(m, 1, table)

Word_List$AvgFreq <- apply(m, 2, f, lookup)

   Word AvgFreg
1 final       7
2 first       7
3 lover       5
4 thing       5

进一步优化是可能的,尤其是使用矢量化方法。

【讨论】:

  • 感谢您的建议!我对 R 很陌生,并且已经阅读以避免循环。我尝试了您的方法,但实际上速度要慢得多。我进行了一些更改以使其正常工作。看看我是否把你的方法搞砸了:编辑:我不知道如何将代码粘贴到评论中,所以我把它放在我的问题的答案中。
【解决方案2】:

回应唐纳德。使用您的方法最终会慢得多,但我必须进行一些更改才能使其与大型单词列表一起使用,如果我搞砸了您的方法,请告诉我:

f <- function(x, tbl){
  res <- integer(5)
  for (i in seq_along(tbl)){
    res[i] <- tbl[[i]][x[i]]
  } 
  sum(res)
}  

Word_List <- data.frame(read.delim("Word List.txt"))
Word_List <- Turn_Vector_List(Word_List)
Word_List2 <- data.frame(read.delim("Word List.txt"))
Word_List_Vector <- Turn_Vector_List(Word_List2)

# Start the clock!
ptm <- proc.time()

m <- data.matrix(Word_List[2:6])
m
lookup <- apply(m, 2, table, simplify = FALSE)
lookup
Word_List$AvgFreq <- apply(m, 1, f, lookup)

 
# Stop the clock
ptm2 <- proc.time() - ptm

 
Word_List2 <- data.frame(read.delim("Word List.txt"))
Word_List_Vector <- Turn_Vector_List(Word_List2)
Word_List2 <- Create_Freq(Word_List_Vector)


ptm3 <- proc.time() - ptm - ptm2

ptm2

# user  system elapsed 
# 0.89    0.78    1.69

ptm3

# user  system elapsed 
# 0.06    0.00    0.06

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    • 2015-03-10
    • 2018-08-16
    • 1970-01-01
    相关资源
    最近更新 更多