r语言 - 将字符串拆分为单独行(创建边缘列表)的有效方法



我目前有以下问题。我处理的是Web-of-Science科学出版物和引文数据,其结构如下:变量"SR"是具有出版物名称的字符串,"CR"是具有包含文章中所有引用参考文献的字符串的变量,由";"分隔。

我现在的任务是在所有具有相应引文的出版物之间创建一个边缘列表,其中每个出版物和引文组合都在一行中。我目前使用以下代码执行此操作:

# Some minimal data for example
pub <- c("pub1", "pub2", "pub3")
cit <- c("cit1;cit2;cit3;cit4","cit1;cit4;cit5","cit5;cit1")
M <- cbind(pub,cit)
colnames(M) <- c("SR","CR")
# Create an edgelist
cit_el <- data.frame() # 
for (i in seq(1, nrow(M), 1)) { #   i=3
  cit <- data.frame(strsplit(as.character(M[i,"CR"]), ";", fixed=T), stringsAsFactors=F) 
  colnames(cit)[1] <- c("SR")
  cit$SR_source <- M[i,"SR"]
  cit <- unique(cit)
  cit_el <- rbind(cit_el, cit)
}

但是,对于大约 10k+ 出版物(往往有 50+ 引用)的大型数据集,脚本运行 15min+。我知道循环通常是在 R 中编码的一种低效方式,但没有找到产生我想要的替代方案。

有人知道一些技巧可以加快速度吗?

这是我

的尝试。我还没有比较不同方法的速度。

首先是人工数据,有 10k 酒吧,100k 可能的引用,每个酒吧最多 80 次引用。

library(data.table)
library(stringr)
pubCount = 10000
citCount = 100000 
maxCitPerPub = 80
pubList <- paste0("pub", seq(pubCount))
citList <- paste0("cit", seq(citCount))
cit <- sapply(sample(seq(maxCitPerPub), pubCount, replace = TRUE),
               function(x) str_c(sample(citList, x), collapse = ";"))
data <- data.table(pub = pubList,
                   cit = cit)

为了进行处理,我使用 stringr::str_split_fixed 将引文拆分为列,并使用 data.table::melt 折叠列。

temp <- data.table(pub = pubList, str_split_fixed(data$cit, ";", maxCitPerPub))
result <- melt(temp, id.vars = "pub")[, variable:= NULL][value!='']

不确定这是否更快,但如果我理解正确,这应该会给出预期的结果

rbindlist(lapply(1:nrow(M), function(i){
data.frame(SR_source = M[i, 'SR'], SR = strsplit(M[i, 'CR'], ';'))
}))

相关内容

最新更新