我目前遇到以下问题。我使用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多次引用)的大型数据集,该脚本运行15分钟+。我知道循环通常是一种低效的R编码方式,但却找不到能产生我想要的东西。
任何人都知道一些让它更快的技巧吗?
答案 0 :(得分:1)
不确定这是否更快,但如果我正确理解,这应该会给出所需的结果
rbindlist(lapply(1:nrow(M), function(i){
data.frame(SR_source = M[i, 'SR'], SR = strsplit(M[i, 'CR'], ';'))
}))
答案 1 :(得分:1)
这是我的尝试。我还没有比较不同方法的速度。
首先是拥有10k个酒吧的人工数据,可能引用10万次,每个酒吧最多引用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!='']