大家好,我正在尝试优化下面的R代码,因为它执行起来非常耗时。我甚至尝试使用R的编译器将函数转换为字节码,但性能反而更差了。所以,有没有办法使用apply函数来重写这段代码呢?
word_separation<-function(inp_data){df<-NULLfor(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数据框有一个包含数据的单列
columnMilk,Bread,Eggs,JamApple,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
回答:
原帖作者指定输入数据由单列组成。因此,我们需要在创建组合之前先分割该列。(Sathish给出的答案悄悄跳过了这一步。)
下面的data.table
解决方案仅使用了一个lapply()
。
数据
编辑:添加了只包含一个单词的行
library(data.table)inp_data <- fread(" columnMilk,Bread,Eggs,JamApple,Milk,BeerButter", sep = "\n")
代码
# 分割字符串,输出为长格式,添加行号以便后续连接molten <- inp_data[, rn := .I][, strsplit(column, ","), by = rn]# 创建所有单词的组合(除了第一个单词)combined <- molten[, unlist( lapply(seq_len(.N - 1), function(.i) as.data.table( combn(V1[-1], .i, paste, collapse = ",", simplify = TRUE)))), by = rn]# 右连接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
编辑:更改了连接方式,以确保只包含一个单词的行也被包括在内。