提高嵌套 for 循环速度 R 创建邻接矩阵
Improve nested for loop speed R creating adjacency matrix
我想创建一个邻接矩阵。该矩阵应显示每个关键字有多少相同的值字符串。
我目前使用两个 for 循环的方法在处理更多数据时需要一段时间。我已经研究过 foreach 包,但无法理解这个例子。如果您能帮助我提高速度,我将不胜感激 ;)
#create reproducible dataset
set.seed(11)
x <- rep('keyword', 10)
y <- seq(1, 10)
z <- rep('value', 10)
df <- tibble::tibble(Keyword = rep(paste0(x,y),4),
Values = paste0(sample(z, 40, replace = TRUE),
sample(y, 40, replace = TRUE)))
#format dataset
temp_df <- df %>%
dplyr::group_by(Keyword) %>%
dplyr::summarise(Values = toString(Values)) %>%
dplyr::ungroup() %>%
dplyr::distinct(Keyword, .keep_all = TRUE)
#initialise adjacency matrix
adj_matrix <- data.frame()
#for loops to iterate through values
for (i in 1:nrow(temp_df)) {
y <- trimws(unlist(strsplit(temp_df$Values[i], split = ',')))
for (g in i:nrow(temp_df)) {
f <- trimws(unlist(strsplit(temp_df$Values[0+g], split = ',')))
z <- y %in% f
adj_matrix[i,g] <- sum(z)
}
}
#name rows and columns
colnames(adj_matrix) <- temp_df$Keyword
rownames(adj_matrix) <- temp_df$Keyword
adj_matrix 是稀疏的(即只有一半被填充),您可以看到哪个关键字共享多少相同的值字符串。有了这个矩阵,我可以很容易地在网络图中显示关系。
提前致谢!
一月
我不清楚您的真实数据是以 df
还是 temp_df
开头的。无论哪种方式,您都可以通过使用 outer()
来避免嵌套循环中的处理,这应该会稍微加快速度。
library(dplyr)
library(purrr)
am_outer <- df %>%
split(f = .$Keyword) %>%
map(pull, Values) %>%
outer(., ., function(x,y) sapply(seq_along(x), function(i) sum(x[[i]] %in% y[[i]])))
am_outer[lower.tri(am_outer)] <- NA
identical(data.frame(am_outer), adj_matrix)
[1] TRUE
如果数据以 temp_df
开头,您可以使用:
temp_df %>%
separate_rows(Values, sep = ", ") %>%
split(f = .$Keyword) %>%
map(pull, Values) %>%
outer(., ., function(x,y) sapply(seq_along(x), function(i) sum(x[[i]] %in% y[[i]])))
我想创建一个邻接矩阵。该矩阵应显示每个关键字有多少相同的值字符串。
我目前使用两个 for 循环的方法在处理更多数据时需要一段时间。我已经研究过 foreach 包,但无法理解这个例子。如果您能帮助我提高速度,我将不胜感激 ;)
#create reproducible dataset
set.seed(11)
x <- rep('keyword', 10)
y <- seq(1, 10)
z <- rep('value', 10)
df <- tibble::tibble(Keyword = rep(paste0(x,y),4),
Values = paste0(sample(z, 40, replace = TRUE),
sample(y, 40, replace = TRUE)))
#format dataset
temp_df <- df %>%
dplyr::group_by(Keyword) %>%
dplyr::summarise(Values = toString(Values)) %>%
dplyr::ungroup() %>%
dplyr::distinct(Keyword, .keep_all = TRUE)
#initialise adjacency matrix
adj_matrix <- data.frame()
#for loops to iterate through values
for (i in 1:nrow(temp_df)) {
y <- trimws(unlist(strsplit(temp_df$Values[i], split = ',')))
for (g in i:nrow(temp_df)) {
f <- trimws(unlist(strsplit(temp_df$Values[0+g], split = ',')))
z <- y %in% f
adj_matrix[i,g] <- sum(z)
}
}
#name rows and columns
colnames(adj_matrix) <- temp_df$Keyword
rownames(adj_matrix) <- temp_df$Keyword
adj_matrix 是稀疏的(即只有一半被填充),您可以看到哪个关键字共享多少相同的值字符串。有了这个矩阵,我可以很容易地在网络图中显示关系。
提前致谢!
一月
我不清楚您的真实数据是以 df
还是 temp_df
开头的。无论哪种方式,您都可以通过使用 outer()
来避免嵌套循环中的处理,这应该会稍微加快速度。
library(dplyr)
library(purrr)
am_outer <- df %>%
split(f = .$Keyword) %>%
map(pull, Values) %>%
outer(., ., function(x,y) sapply(seq_along(x), function(i) sum(x[[i]] %in% y[[i]])))
am_outer[lower.tri(am_outer)] <- NA
identical(data.frame(am_outer), adj_matrix)
[1] TRUE
如果数据以 temp_df
开头,您可以使用:
temp_df %>%
separate_rows(Values, sep = ", ") %>%
split(f = .$Keyword) %>%
map(pull, Values) %>%
outer(., ., function(x,y) sapply(seq_along(x), function(i) sum(x[[i]] %in% y[[i]])))