警告:事实证明,我的原始版本存在一些范围界定问题,也未达到预期的目标。
我有一个100000(一万)条记录的数据集,我想将其分成多行。每个记录都有一个字段,该字段包含一个字符串,该字符串的名称由8个项目组成,并用分号(;)分隔。最终结果是每1行原始数据就有8行。
我编写了以下函数来帮助我实现这一目标,但它似乎并不是很高效,这反过来意味着执行该过程的时间不可能太长(我已经让它运行了至少30分钟,现在仍然没有还没完成)。因此,我正在寻找各种方法来改善运行时间的提示。
一点点背景:
row[1]
是用分号分隔的字符串。
row[5]
是项集合的索引,该项集合必须与单独的项一起保存,以便以后可以将它们关联起来。
toSingleItems <- function(data, sep = ';') {
returnVal <- vector("list", nrows(data) * 8)
i <- 1
apply(data, 1, FUN = function(row) {
splitDeck = str_split(row[1], sep)
lapply(splitDeck, FUN=function(item){
returnVal[[i]] <- c(row[5], item)
i <- i + 1
})
})
return(returnVal)
}
欢迎任何提示,谢谢!!
偷偷摸摸的编辑:显而易见的解决方案当然是以任何方式减少数据集。我已经做到了这一点(达到10000),但是即使那样,性能仍然非常糟糕。
数据可能如下所示:
"a;b;c;d;w;x;y;z"
"e;f;g;h;i;j;k;l"
在这种情况下,输出将如下所示:
1, "a"
1, "b"
1, "c"
1, "d"
1, "w"
1, "x"
1, "y"
1, "z"
2, "e"
2, "f"
2, "g"
2, "h"
2, "i"
2, "j"
2, "k"
2, "l"
答案 0 :(得分:1)
这是一个更简单的示例,可能代表您的数据?
df = data.frame(x = c("a;b;c;d", "e;f;g;h"), y = 1:2, stringsAsFactors=FALSE)
要拆分x
,我做了
elts = strsplit(df$x, ";")
我们需要知道每个元素的长度,即lengths(elts)
。
然后我把东西放回去
data.frame(x = unlist(elts), y = rep(y, lengths(elts))
也许一个概括就是按照上面的方法进行分割和计算长度,复制整个数据集
idx = rep(seq_len(nrow(df)), lengths(elts))
df = df[idx,]
并更新相关列
df$x = unlist(elts)
tidyr
软件包提供了非常方便的功能
df %>% tidyr::separate_rows(x, sep = ";")
答案 1 :(得分:1)
看看下面的代码是否有帮助。
library(tidyverse)
df = data.frame(id= c(1,2), value=c("a;b;c;d;w;x;y;z", "e;f;g;h;i;j;k;l"))
df = df %>%
mutate(value = str_split(value,pattern=";", n=8)) %>% # transform the string to list
unnest # list to individual rows