【问题标题】:How can this slow R code be rewritten to be more efficient?如何将这个缓慢的 R 代码重写为更高效?
【发布时间】:2017-03-13 16:47:06
【问题描述】:

大家好,我正在尝试使用 for 循环优化下面的 R 代码,因为执行需要很长时间。我什至尝试在 R 中编译器将函数转换为字节码,但性能更差。那么,有没有办法用应用函数编写这段代码

word_separation<-function(inp_data){
df<-NULL
for(k in 1:nrow(inp_data)){
    vec<-unlist(strsplit(as.vector(inp_data[k,]),split=","))
        if(length(vec)==1){
            df<-rbind(df,data.frame(first_col=vec,second_col=vec))
        }else{
            temp_df<-NULL
            for(i in 2:length(vec)){
                for(j in i:length(vec){
                    temp_df<-rbind(temp_df,data.frame(first_col=vec[1],second_col=paste(vec[i:j],collapse=",")))
                }
                df<-rbind(df,temp_df)
                df[df==""]<-NA
                df<-df %>% unique() %>% na.omit()
            }
        }
    }
    return(df)
}

这里我的 inp_data 数据框有单列数据

    column
Milk,Bread,Eggs,Jam
Apple,Milk,Beer

当传递给函数时,返回一个包含列的数据框,第一列包含第一个单词,第二列包含数据框中其他单词的组合。

 first_col     second_col
   Milk          Bread
   Milk     Bread,Eggs
   Milk Bread,Eggs,Jam
   Milk           Eggs
   Milk       Eggs,Jam
   Milk            Jam
   Apple           Milk
   Apple      Milk,Beer
   Apple           Beer

【问题讨论】:

  • 描述一下这个方法应该做什么?
  • 你正在尽一切可能使这个运行缓慢。始终为循环预先分配存储空间(将df 设置为某个大小并填充它,如果您不知道df 有多大,则仅当您接近填充它时才增加df 的大小开始。);使用矩阵或列表而不是数据框; 从不在循环中的每次迭代中增长对象 - 你填充对象但从不增长它们(除非你已经填充它们并且还没有完成迭代);在循环内尽可能少地执行操作/函数调用 - 将操作移至更高级别或循环外以避免过多调用
  • 感谢回复,能否请您详细说明或举一些例子提醒代码
  • 另外,您可以查看this Q&A 了解更多关于-apply 功能

标签: r algorithm machine-learning apply


【解决方案1】:

OP 已指定输入数据由单列组成。所以我们需要在创建组合之前拆分列。 (The answer given by Sathish 默默地跳过了这一步。)

下面的data.table 解决方案只使用了一个lapply()

数据

编辑:添加了只有一个单词的行

library(data.table)
inp_data <- fread("    column
Milk,Bread,Eggs,Jam
Apple,Milk,Beer
Butter", sep = "\n")

代码

# split strings, output in long format, add row number for later join
molten <- inp_data[, rn := .I][, strsplit(column, ","), by = rn]
# create combinations of all words (except the first one)
combined <- molten[, unlist(
  lapply(seq_len(.N - 1), function(.i) as.data.table(
    combn(V1[-1], .i, paste, collapse = ",", simplify = TRUE)))), by = rn]
# right join
combined[molten[, .(rn, first_col = first(V1)), by = rn], 
         .(rn, first_col, second_col = V1), on = "rn"]
#    rn first_col     second_col
# 1:  1      Milk          Bread
# 2:  1      Milk           Eggs
# 3:  1      Milk            Jam
# 4:  1      Milk     Bread,Eggs
# 5:  1      Milk      Bread,Jam
# 6:  1      Milk       Eggs,Jam
# 7:  1      Milk Bread,Eggs,Jam
# 8:  2     Apple           Milk
# 9:  2     Apple           Beer
#10:  2     Apple      Milk,Beer
#11:  3    Butter             NA

编辑:更改了连接以确保只包含一个单词的行也包括在内。

【讨论】:

    猜你喜欢
    • 2020-01-18
    • 1970-01-01
    • 2018-08-31
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 2015-08-31
    • 2011-06-28
    • 1970-01-01
    相关资源
    最近更新 更多