Я новичок в R и в настоящее время работаю с данными сотрудничества в виде списка ребер с 32 столбцами и около 200 000 строк. Я хочу создать матрицу (совместного) возникновения, основанную на взаимодействии между странами. Однако я хочу подсчитать количество взаимодействий по общему количеству объекта.
Основной пример желаемого результата
Если в одной строке «Англия» встречается три раза, а «Китай» только один раз, результатом должна быть следующая матрица.
England China
England 3 3
China 3 1
Воспроизводимый пример
df <- data.frame(ID = c(1,2,3,4),
V1 = c("England", "England", "China", "England"),
V2 = c("Greece", "England", "Greece", "England"),
V32 = c("USA", "China", "Greece", "England"))
Соответственно, пример фрейма данных в настоящее время выглядит так:
ID V1 V2 ... V32
1 England Greece USA
2 England England China
3 China Greece Greece
4 England England England
.
.
.
Желаемый результат
Я хочу подсчитать (совпадения) по строкам и независимо от порядка, чтобы получить матрицу (совместных) вхождений, которая учитывает низкие частоты краевых циклов (например, Англия-Англия), что приводит к следующему результату:
China England Greece USA
China 2 2 2 0
England 2 6 1 1
Greece 2 1 3 1
USA 0 1 1 1
Что было испробовано до сих пор
Я использовал igraph
, чтобы получить матрицу смежности с совпадениями. Однако он вычисляет - как и предполагалось - не более двух взаимодействий одних и тех же двух объектов, в некоторых случаях оставляя мне значения намного ниже фактической частоты объектов по строке / публикации.
df <- data.frame(ID = c(1,2,3,4),
V1 = c("England", "England", "China", "England"),
V2 = c("Greece", "England", "Greece", "England"),
V32 = c("USA", "China", "Greece", "England"))
# remove ID column
df[1] <- list(NULL)
# calculate co-occurrences and return as dataframe
library(igraph)
library(Matrix)
countrydf <- graph.data.frame(df)
countrydf2 <- as_adjacency_matrix(countrydf, type = "both", edges = FALSE)
countrydf3 <- as.data.frame(as.matrix(forceSymmetric(countrydf2)))
China England Greece USA
China 0 0 1 0
England 0 2 1 0
Greece 1 1 0 0
USA 0 0 0 0
Я предполагаю, что должно быть простое решение с использованием base
и / или dplyr
и / или table
и / или reshape2
, аналогичных [1], [2], [3], [4] или [5], но пока ничего не помогло, и я не смог настроить код в соответствии со своими потребностями. Я также пробовал использовать [6], однако, здесь применима та же проблема.
library(tidry)
library(dplyr)
library(stringr)
# collapse observations into one column
df2 <- df %>% unite(concat, V1:V32, sep = ",")
# calculate weights
df3 <- df2$concat %>%
str_split(",") %>%
lapply(function(x){
expand.grid(x,x,x,x, w = length(x), stringsAsFactors = FALSE)
}) %>%
bind_rows
df4 <- apply(df3[, -5], 1, sort) %>%
t %>%
data.frame(stringsAsFactors = FALSE) %>%
mutate(w = df3$w)
Я был бы рад, если бы кто-нибудь указал мне правильное направление.
tab = table(df$ID[row(df[-1])], as.matrix(df[-1])); df1 = crossprod(tab); diag(df1) = colSums(tab); df1
08.01.2020