본문 바로가기
R언어

R언어로 네트워크를 구축해보자

by 할10000 2022. 5. 24.

오늘은 들어가기 앞서 사전 펼치듯 몇 가지 용어에 대해 설명해야할 필요가 있다. 

 

네트워크(Network): 그물망

그래프를 바탕으로 함. 그래프의 가지에 특정한 정량적인 값들을 대응시킨 가중 그래프에 해당한다. 

응용: 각 지점 간의 최소 경로를 찾는 최적화 문제, 친구 관계, 협업 관계, 인터넷 연결망 구조, 웹의 연결, 질병 전파, 분자 그래프 등으로 표현되는 다양한 사회 및 자연 현상을 파악하는데 응용.

 

중심성 | 중심화

연결정도: 각 노드가 어느 정도로 많은 관계를 맺고 있는지를 나타내는 지표 | 연결 정도의 전체 경향

근접: 한 점이 다른 모든 점들에 얼마나 가까운가를 나타내는 지표 | 근접 정도의 전체 경향

중개: 연결망서 한 노드가 다른 노드들 사이에 위치하는 정도를 나타내는 지표 | 중개 정도의 전체 경향

 

밀도: 네트워크서 이론적으로 연결 가능한 최대연결수(풀 매쉬: 밀도=1) 대비 실제 얼마나 많은 관계를 맺고 있는가를 나타낸 상대적인 비율. 

 

최단경로: 두 노드 간 가장 짧은 연결 경로

-거리: 경로 상의 연결 수

평균거리: 네트워크를 구성한느 두 노드 간 평균 거리

 

네트워크엔 여러 모형이 있다. 별처럼 중심점 하나서 뻗어나가는 모양의 별형, Y처럼 생긴 Y형, 원처럼 생긴 원형은 그 대표적인 녀석이다. 우린 네트워크 값만 보고도 어떤 모형에 가까운지 알아낼 수 있다. 이걸 생성할 수 있는 코드의 시작부는 아래와 같다. 

make_star()
make_ring()
make_graph()

이제 네트워크 및 관련 용어들의 뜻을 알았다. 그럼 카테고리에 걸맞도록, R언어에서 이 네트워크라는 것과 어떻게 놀아날 수 있는지 알아보도록 하자. igraph라는 패키지를 설치해야 한다. 이미 깔려있으면 install 부분은 생략하자. 

install.packages("igraph")
library(igraph)

igraph가 컴퓨터에 안착했다면 다음 단계로 넘어가자. 

{
G.star <- make_star(6, mode="undirected", center=1) %>%
    set_vertex_attr("name", value = c("A", "B", "C", "D", "E", "F"))
G.star
plot(G.star, vertex.color=rainbow(6), vertex.size=60)

tkplot(G.star, vertex.color=rainbow(6), vertex.size=20)

G.ring <- make_ring(6, directed = FALSE, circular = TRUE) %>%
    set_vertex_attr("name", value = c("A", "B", "C", "D", "E", "F"))
tkplot(G.ring, vertex.color=rainbow(6), vertex.size=20)

G.Y <- make_graph(edges=NULL, n=NULL, directed=FALSE)
G.Y <- G.Y + vertices("A", "B", "C", "D", "E", "F")
G.Y <- G.Y + edges("A", "B",
                   "A", "C",
                   "A", "D",
                   "D", "E",
                   "E", "F")
tkplot(G.Y, vertex.color=rainbow(6), vertex.size=20)
}

R언어를 쓰면서 터득한 잔기술이 하나 있는데, 바로 중괄호를 쓰는 것이다. ctr+Enter 매번 누르는 것도 귀찮은 일이니까, 아예 하나로 묶어서 한 번에 처리할 수 있게 하는 것이다. 다만 이 방식에 단점이 있다면, R 코드가 하나하나 실행되는 걸 확인하기엔 너무 빠르다는 것이다. 

 

이번 게시글에선 다른 잔기술도 소개한다. 줄 앞부분의 tkplot을 주목하자. 

tkplot(G.ring, vertex.color=rainbow(6), vertex.size=20)

모 정당의 텃밭인 TK가 아니다. 이 tk는 R스튜디오의 plots창이 아닌, 별도의 윈도우 창에 plot 결과를 생성하는 물건이다. 여러 결과를 동시에 띄워놓고 보고 싶다면 이것만한 물건이 없다. (적어도 내가 알기로는 그렇다)

 

지금은 고작 간단한 그림일 뿐이지만, 현실에선 눈 빠질 정도로 복잡한 모양이 되기 십상이다. 이럴 때 우린 무엇을 통해 이 녀석들의 밀도나 중점 등을 파악할 수 있을까. 

# 연결 정도 중심성과 중심화
{
degree(G.star, normalized = FALSE)
degree(G.star, normalized = TRUE)
CD <- centralization.degree(G.star, normalized = FALSE)
CD

CD <- centralization.degree(G.ring, normalized = FALSE)
CD

Tmax <- centralization.degree.tmax(G.ring)
Tmax
CD$centralization / Tmax
}
# 근접 중심성과 중심화
{
closeness(G.star, normalized=FALSE)

closeness(G.star, normalized=TRUE)

CC <- centralization.closeness(G.star, normalized = FALSE)
CC
CC$centralization / (6-1)

CC$theoretical_max / (6-1)

CC$centralization / CC$theoretical_max

CC
}
# 중개 중심성과 중심화
{
betweenness(G.star, normalized=FALSE)

betweenness(G.star, normalized=TRUE)

CB <- centralization.betweenness(G.star, normalized=FALSE)
CB
CB$centralization

CB$theoretical_max

CB$centralization / CB$theoretical_max
CB
}

실행하면 그래프는 없는 대신, 이런 메시지를 얻을 수 있다. 

> # 근접 중심성과 중심화
> closeness(G.star, normalized=FALSE)
        A         B         C         D         E         F 
0.2000000 0.1111111 0.1111111 0.1111111 0.1111111 0.1111111 
> closeness(G.star, normalized=TRUE)
        A         B         C         D         E         F 
1.0000000 0.5555556 0.5555556 0.5555556 0.5555556 0.5555556 
> CC <- centralization.closeness(G.star, normalized = FALSE)
> CC
$res
[1] 1.0000000 0.5555556 0.5555556 0.5555556 0.5555556 0.5555556

$centralization
[1] 2.222222

$theoretical_max
[1] 2.222222

> CC$centralization / (6-1)
[1] 0.4444444
> CC$theoretical_max / (6-1)
[1] 0.4444444
> CC$centralization / CC$theoretical_max
[1] 1
> CC
$res
[1] 1.0000000 0.5555556 0.5555556 0.5555556 0.5555556 0.5555556

$centralization
[1] 2.222222

$theoretical_max
[1] 2.222222

네트워크 밀도 / 최단거리(A - E 間)및 평균 거리 구하는 코드

# 네트워크 밀도
graph.density(G.star)

graph.density(G.Y)

graph.density(G.ring)

# 최단경로와 평균 거리
shortest.paths(G.Y)

distances(G.Y, v = "A", to="E")

get.shortest.paths(G.Y, "A", "E")$vpath[[1]]

average.path.length(G.Y)

실행결과

> # 최단경로와 평균 거리
> shortest.paths(G.Y)
  A B C D E F
A 0 1 1 1 2 3
B 1 0 2 2 3 4
C 1 2 0 2 3 4
D 1 2 2 0 1 2
E 2 3 3 1 0 1
F 3 4 4 2 1 0
> distances(G.Y, v = "A", to="E")
  E
A 2
> get.shortest.paths(G.Y, "A", "E")$vpath[[1]]
+ 3/6 vertices, named, from 74f45f1:
[1] A D E
> average.path.length(G.Y)
[1] 2.133333

페이스북 연결망 실습: 글쓴이는 이를 c드라이브 TEMP 폴더에 설치했다. 

CA-AstroPh.txt
5.04MB
facebook_combined.txt
0.81MB

열어보니 웬 숫자열이 세로로 한참 뻗어 있더라. 

아래의 첫번째 프로그램을 실행하려고 하면 파일 저장소를 찾는다. 위의 파일을 찾아서 선택해주면 된다. 글쓴이는 facebook으로 시작하는 파일을 택했다. 

# 11.4 페이스북 사용자 네트워크 분석
# 페이스북 사용자 데이터 읽기와 그래프 출력
# install.packages("igraph"")
library(igraph)
{
df.fb <- read.table(file.choose(), header=F)
head(df.fb)

tail(df.fb)

G.fb <- graph.data.frame(df.fb, directed=FALSE)
G.fb

par(mar=c(0,0,0,0))


plot(G.fb,
     vertex.label = NA,
     vertex.size = 10,
     vertex.color = rgb(0,1,0,0.5))

dev.off()
}
# 1~50번째 사용자들 간의 그래프
{
V(G.fb)$name

v.set <- V(G.fb)$name[1:50]
v.set
G.fb.part <- induced_subgraph(G.fb, v=v.set)
tkplot(G.fb.part,
       vertex.label.cex = 1.2,
       vertex.size = degree(G.fb.part)*1.5,
       vertex.color = "yellow",
       vertex.frame.color = "gray")
}
# ID가 1인 사용자와 연결된 그래프
{
v2 <- which(V(G.fb)$name == "1")
v2

v.set <- neighbors(G.fb, v=v2)
v.set

v3 <- c(v2, v.set)
v3
G.fb.id <- induced_subgraph(G.fb, v=v3)
V(G.fb.id)$color <- ifelse(V(G.fb.id)$name == "1", "red", "yellow")
tkplot(G.fb.id,
       vertex.label.cex = 1.2,
       vertex.size = degree(G.fb.id)*1.5,
       vertex.frame.color = "gray")
}
# 연결정도가 가장 큰 사용자와 연결된 그래프
{
v.max <- V(G.fb)$name[degree(G.fb)==max(degree(G.fb))]
v.max

degree(G.fb, v.max)

v.max.idx <- which(V(G.fb)$name == v.max)
v.max.idx

v.set <- neighbors(G.fb, v=v.max.idx)
v3 <- c(v.max.idx, v.set)
v3
G.fb_2 <- induced_subgraph(G.fb, v=v3)
V(G.fb_2)$color <- ifelse(V(G.fb_2)$name == v.max, "red", "yellow")
V(G.fb_2)$label <- ifelse(V(G.fb_2)$name == v.max, v.max, NA)
V(G.fb_2)$size <- ifelse(V(G.fb_2)$name == v.max, 50, 5)
plot(G.fb_2)
}
# 연결정도 중심성과 중심화 지표
{
degree(G.fb, normalized=FALSE)

degree(G.fb, normalized=TRUE)

CD <- centralization.degree(G.fb, normalized = FALSE)
CD
CD$centralization

Tmax <- centralization.degree.tmax(G.fb)
Tmax

CD$centralization / Tmax
}
# 근접 중심성과 중심화 지표
closeness(G.fb, normalized=FALSE)

closeness(G.fb, normalized=TRUE)

CB <- centralization.closeness(G.fb, normalized = FALSE)
n <- vcount(G.fb)
n

CB$centralization / (n-1)

CB$theoretical_max / (n-1)

CB$centralization / CB$theoretical_max

# 중개 중심성과 중심화 지표
betweenness(G.fb, normalized=FALSE)

betweenness(G.fb, normalized=TRUE)

CB <- centralization.betweenness(G.fb, normalized = FALSE)
CB$centralization

CB$theoretical_max

CB$centralization / CB$theoretical_max

# 밀도 
graph.density(G.fb)

# 거리 
shortest.paths(G.fb)[1:10, 1:10]

distances(G.fb, v = "3", to="7")

get.shortest.paths(G.fb, "3", "7")$vpath[[1]]

average.path.length(G.fb)

# 연결정도 분포
plot(degree(G.fb),
     xlab="사용자 ID", ylab="연결 정도",
     main="사용자별 연결정도",
     type='h')

x <- degree(G.fb, normalized=F)
summary(x)

hist(x,
     xlab="연결 정도", ylab="빈도",
     main="연결정도 분포",
     breaks=seq(0, max(x), by=1))

G.fb.dist <- degree.distribution(G.fb)
plot(G.fb.dist,
     type="h",
     xlab="연결정도 분포", ylab="확률밀도",
     main="연결정도 분포")

실행시키면 뭐가 빠졌나? 어디 잘못되었나 싶을 정도로 느리게 실행된다. 그래봤자 상대적인 것이라 15초 안에 끝난다. 

그러고나면 몇 가지 노드망 그림들이 촤라락 등장한다. 

 

100번째 있는 이웃. 저장하고 전체 노드 대비 찾아온다. 

가장 연결이 많이된 인싸 107번 노드 색을 붉은색으로 하고, 나머지는 노랑으로 해서 구별한다. 

 

이미지는 나중에 추가하겠다. 

 

 

더 알고 싶으면 아래의 링크도 참고해보자. 

 

4 장 R을 이용한 네트워크 분석 | 빅데이터분석및실습(2)

네트워크의 특성치 - 중심성과 밀도 그래프 중심성 (centralization) : 전체 네트워크에서 가장 영향력 있는 노드의 다른 노드들에 대한 상대적인 영향력을 측정 \[ C_D= \frac{\sum_{i=1}^{|V|} (C_D^* - C_D(i))}{

bigdata.dongguk.ac.kr

 

.

 

'R언어' 카테고리의 다른 글

인공지능 신경망 구축  (0) 2022.06.07
R 스튜디오 테마 바꾸기  (0) 2022.04.05
R언어 3강  (0) 2022.03.29
R언어 연산  (0) 2022.03.22