1편The R SNA Ecosystem
R의 SNA 생태계 — 네 패키지의 역할 분담
1.1 누가 무엇을 맡는가 (Division of Labor)
R에서 네트워크를 다루는 패키지는 두 계보로 갈린다. 이 사실을 모르고 시작하면 반드시 헤맨다.
| 패키지 | 계보 | 맡는 일 |
|---|---|---|
| network | statnet | 자료구조. 분석 함수는 거의 없다. 네트워크를 담는 그릇(network 객체)을 정의하고,
정점·간선에 속성을 붙이는 일을 한다. sna와 ergm이 이 그릇 위에서 돌아간다. |
| sna | statnet | 사회학 전통의 분석 도구. 함수 273개.
중심성, 블록모델링, QAP 검정 등 사회학 문헌에 나오는 지표가 강하다.
인접행렬(matrix)을 그대로 받아 준다는 게 큰 장점. |
| igraph | 독립 | 그래프 이론·전산 전통의 분석 도구. C로 짜여 빠르고,
커뮤니티 탐지·k-코어·무작위 그래프 모형이 압도적으로 풍부하다.
대신 igraph 전용 객체만 받는다. |
| intergraph | 다리 | 번역기. asIgraph() / asNetwork() 두 함수가 사실상 전부다.
속성까지 같이 옮겨 준다. |
1.2 그럼 igraph만 쓰면 되지 않나?
위 그림만 보면 igraph 혼자 그릇과 알고리즘을 다 가졌으니, 나머지 셋은 군더더기처럼 보인다. 실제로 기술 통계까지는 igraph만으로 된다 — 중심성, 밀도, 커뮤니티 탐지, 그림까지 전부. 그런데 사회과학 분석은 네 지점에서 igraph만으로는 막히고, 거기가 statnet 계보를 같이 켜는 이유다.
| 막히는 지점 | 왜 statnet 쪽이 필요한가 |
|---|---|
| ① 사회학 전통 기법 | 블록모델링·구조적 등위(equiv.clust, blockmodel), QAP 검정(qaptest, netlogit), 중개 역할 분석(brokerage)은 igraph에 구현 자체가 없다. "지위가 비슷한 학생 묶음은 어디인가"(블록모델링), "친교 관계와 도움 관계는 겹치는가"(QAP) 같은 질문의 답이 여기에 있다. |
| ② 통계 모형(ERGM) | "동성이면 친구일 확률이 유의하게 높은가"를 검정하는 ergm()은 statnet 계보라 network 그릇만 받는다. 기술 통계에서 추론 통계로 넘어가는 순간 igraph 객체로는 못 간다. |
| ③ 문헌 재현 | 같은 지표라도 정규화 방식·비연결 그래프 처리 같은 기본값이 계보마다 달라 수치가 다르게 나올 수 있다. 사회학 교재·논문(Wasserman–Faust 계열)의 옵션 체계(gmode=, cmode=)와 1:1로 맞는 쪽은 sna다. 논문 수치를 재현·대조하려면 그 논문이 쓴 구현이 필요하다. |
| ④ 행렬 입출력 | 교실 소시오메트리 명부는 인접행렬로 오간다. sna는 matrix를 그대로 받지만 igraph는 매번 전용 객체로 변환해야 한다. 행렬 연산과 병행하는 빠른 확인에는 sna가 덜 번거롭다. |
반대 방향도 성립한다. 커뮤니티 탐지·k-코어·대규모 처리 속도는 igraph가 압도적이라 statnet만으로도 안 된다. 어느 쪽도 상대의 부분집합이 아니다.
install.packages(c("network", "sna", "igraph", "intergraph"))
library(network) # 자료구조
library(sna) # 사회학 지표
library(igraph) # 그래프 알고리즘
library(intergraph) # 변환
이 프로젝트에 깔린 판본: network 1.20, sna 2.8, igraph 2.3.3, intergraph 2.0.4, ergm 4.12 (R 4.5.1).
1.3 가장 먼저 부딪히는 벽: 이름 충돌 (Function Masking)
위 순서로 패키지를 켜면 콘솔에 이런 경고가 쏟아진다.
The following objects are masked from 'package:sna':
betweenness, bonpow, closeness, components, degree,
dyad.census, evcent, hierarchy, is.connected, neighborhood,
triad.census
같은 이름의 함수가 양쪽에 다 있다. 나중에 켠 igraph가 sna를 가려서(mask), 그냥 degree()라고 쓰면 igraph 것이 불린다. 문제는 두 함수의 인자 이름이 서로 다르다는 점이다.
closeness(adj, cmode = "suminvdir")
Error in closeness(adj, cmode = "suminvdir") :
unused argument (cmode = "suminvdir")
교재대로 썼는데 에러가 난다. 코드가 틀린 게 아니라 다른 패키지의 함수가 불린 것이다. sna는 cmode=, igraph는 mode=를 쓴다.
sna::closeness(adj, gmode = "digraph", cmode = "suminvdir") # ✔ 확실
igraph::closeness(g, mode = "out") # ✔ 확실
closeness(adj, cmode = "suminvdir") # ✘ 어느 쪽인지 모름
conflicts.policy 옵션은 경고만 없애 줄 뿐,
어느 함수가 불릴지는 바꾸지 않는다. 경고를 껐다고 문제가 사라진 게 아니다.
충돌하는 이름 중 초보자가 실제로 자주 쓰는 것: degree, closeness, betweenness, evcent, components, dyad.census, triad.census, neighborhood. 이 여덟 개는 예외 없이 ::를 붙이는 습관을 들이는 게 제일 싸게 먹힌다.