Я уточняю предыдущий вопрос, который задал здесь: Расчет соотношения взаимных связей для каждого узла в графике
Ответы были очень полезными, но я понял, что один из расчетов выходит неправильно. Я пытаюсь вычислить соотношение взаимных преимуществ к исходящей степени - другими словами, какой процент людей, которых я называю друзьями, назначают меня в друзья?
Когда студенты не назначают друзей (исходящая степень 0), они не включаются в мой расчет взаимных связей. Поскольку у них не может быть никаких взаимных связей, я хочу, чтобы их взаимность была рассчитана как 0. Их соотношение взаимных связей / исходящей степени также должно быть равно 0.
Вот пример:
library(igraph)
###Creating sample edgelist###
from<- c("A", "A", "A", "B", "B", "B", "C", "D", "D", "E")
to<- c("B", "C", "D", "A", "E", "D", "A", "B", "C", "E")
weight<- c(1,2,3,2,1,3,2,2,1,1)
g2<- as.matrix(cbind(from,to, weight))
###Converting edgelist to network###
g3=graph.edgelist(g2[,1:2])
E(g3)$weight=as.numeric(g2[,3])
###Removing self-loop###
g3<-simplify(g3, remove.loops = T)
Здесь степень выхода E равна 1, а исходящая степень равна 0. Я создаю цикл для E, чтобы векторы входов и исходов оставались одинаковой длины, а затем удаляю его.
Далее я смотрю, какие номинации принимаются взаимностью:
recip<-is.mutual(g3)
recip<-as.data.frame(recip)
Затем я создаю список редактирования из g3 и добавляю recip
во фрейм данных:
###Creating edgelist and adding recipe###
edgelist<- get.data.frame(g3, what = "edges")
colnames(edgelist)<- c("from", "to", "weight")
edgelist<- cbind(edgelist, recip)
edgelist
> edgelist
from to weight recip
1 A B 1 TRUE
2 A C 2 TRUE
3 A D 3 FALSE
4 B A 2 TRUE
5 B D 3 TRUE
6 B E 1 FALSE
7 C A 2 TRUE
8 D B 2 TRUE
9 D C 1 FALSE
Вот тут и начинаются проблемы. Поскольку E нет в from
, его также нет в объектах, которые я создаю ниже.
Затем я создаю таблицу с исходящей степенью и добавляю имена вершин:
##Creating outdegree and adding vertex IDs##
outdegree<- as.data.frame(degree(g3, mode = "out"))
ID<-V(g3)$name
outdegree<-cbind(ID, outdegree)
colnames(outdegree) <- c("ID","outdegree")
rownames(outdegree)<-NULL
outdegree
Outdegree
выходит именно так, как я хочу:
ID outdegree
1 A 3
2 B 3
3 C 1
4 D 2
5 E 0
Когда я подсчитываю количество взаимных связей для каждого узла, E не включается, поскольку я использую столбец from
из edgelist
, о котором я говорил выше.
##Calculating number of reciprocated ties##
recip<-aggregate(recip~from,edgelist,sum)
colnames(recip)<- c("ID", "recip")
recip
> recip
ID recip
1 A 2
2 B 2
3 C 1
4 D 1
Так вот в чем проблема. Если попытаться создать таблицу с отношением взаимных связей к исходящей степени, E не будет включено:
##Creating ratio table##
ratio<-merge(recip, outdegree, by= "ID")
ratio<-as.data.frame (recip$recip/ratio$outdegree)
ratio<- cbind(recip$ID, ratio)
colnames(ratio)<- c("ID", "ratio")
ratio
ID ratio
1 A 0.6666667
2 B 0.6666667
3 C 1.0000000
4 D 0.5000000
В конечном счете, мне нужна строка в ratio
для E, равная 0. Поскольку соотношение здесь будет 0/0 (0 взаимных связей / 0 исходящих градусов), я, вероятно, получил бы NaN, но я могу легко преобразовать его в 0, так что было бы хорошо.
Я мог бы обойти это и экспортировать данные в Excel, выполнить вычисления вручную и упростить задачу. Но это не поможет мне улучшить мои навыки программирования, а у меня есть множество сетей, которые нужно запустить, так что это тоже довольно неэффективно.
Есть мысли о том, как это автоматизировать?
Еще раз спасибо за помощь.
E
не отображается, потому что E
отсутствует в столбце from
фрейма данных recip
! Это только в to
.
Вы можете aggregate
на обоих столбцах, а затем объединить.
r1 <- aggregate(recip~from,edgelist,sum)
colnames(r1) <- c("ID", "recip")
r2 <- aggregate(recip~to,edgelist,sum)
colnames(r2) <- c("ID", "recip")
recip <- merge(r1,r2, all = T) # all = T gives the union of the df's
Который дает:
ID recip
1 A 2
2 B 2
3 C 1
4 D 1
5 E 0
Также с пиплингом:
library(dplyr)
edgelist %>%
aggregate(recip~from,.,sum) %>%
rename(ID = from) %>%
merge(., edgelist %>%
aggregate(recip~to,.,sum) %>%
rename(ID = to),
all = T)
Извините - опубликовано преждевременно, время на редактирование закончилось. А вот и остальное: решение для пиплинга сработало, как шарм. Однако у меня возник вопрос по первому. Похоже, что оба r1 и r2 объединяются "в". Это опечатка? Когда я пытаюсь закодировать r1 для агрегирования «из», он снова не учитывает E, а когда я объединяю r1 и r2, E остается вне вывода. Я обязательно воспользуюсь стратегией конвейерной обработки, но не могли бы вы рассказать мне, что не так с первой? Еще раз спасибо!
@GaryDeYoung Если этот ответ был полезен, вы должны хотя бы проголосовать за него. Если он действительно отвечает на ваш вопрос, примите его как ответ.
@GaryDeYoung, да, это была опечатка! Кроме того, добавьте all = T
к merge
, чтобы сохранить все наблюдения как из r1
, так и из r2
.
@paqmo Понятно! Теперь все это имеет смысл. Кстати, только что принял ответ. Простите за опоздание.
Это действительно полезно - спасибо. Я знал, что проблема возникла из-за того, что E не находится в "от", но не знал, как туда добраться.