graph.correlations

Sylen·2025년 1월 4일

아래 튜토리얼은 graph-tool 라이브러리에서 제공하는 corr_hist 함수를 통해, 네트워크에서 “어떤 노드 속성(차수 등)이 다른 노드(이웃)의 어떤 속성과 어떻게 상관되어 있는가”를 히스토그램(이차원 형태)으로 구하고 시각화하는 방법을 단계별로 살펴봅니다. 초보자도 이해하기 쉽게 친절한 한글 설명파이썬 코드 예시를 상세하게 제시하였으니 참고하시기 바랍니다.


1. corr_hist 함수란?

corr_hist(g, deg_source, deg_target, bins=[[0,1],[0,1]], weight=None, float_count=True) 는 네트워크에서

  • 각 노드(=소스 노드)마다, deg_source가 지정하는 노드 속성을 확인하고,
  • 그 소스 노드가 갖는 이웃(=타깃 노드)들의 deg_target 속성을 확인하여,
  • ‘(소스 속성, 타깃 속성)’ 쌍이 얼마나 많이 등장했는지(혹은 간선 가중치에 따라)를 “2차원 히스토그램(bin counts)” 형태로 계산해 줍니다.

예) ((\text{소스노드 out-degree}, \text{타깃노드 out-degree})) 값 쌍이 네트워크 전체에서 몇 번 등장하는지.
도시·교통 관점에서 보면, 교차로(노드)마다 교통량(혹은 차수)이 있고, 이웃 교차로들의 교통량과의 상관 분포를 시각적으로 확인할 수 있습니다.


2. 주요 파라미터

  1. g: Graph 객체 (분석 대상 네트워크).
  2. deg_source, deg_target:
    • 문자열 "in", "out", "total" (노드의 차수를 의미)
    • 혹은 VertexPropertyMap (노드별 스칼라 속성)
    • 예) "out"을 두 번 주면, “소스노드 out-degree vs. 타깃노드 out-degree” 히스토그램이 됨.
  3. bins:
    • 히스토그램의 구간(bin) 경계값 지정.
    • 기본값은 [[0,1],[0,1]], 이는 자동 bin 세팅에 사용되지만, 실무에서는 적절히 범위를 설정해야 합니다.
    • 2차원 형태이므로, [ [소스 bin 경계], [타깃 bin 경계] ] 이렇게 2개 리스트로 제공.
    • 예) 만약 bins=[[0,50,1],[0,50,1]] 라면, 0부터 50까지 1씩 증가하는 간격으로 bin을 만든다는 의미(차수가 50 이하인 그래프라고 가정).
  4. weight: (optional) 간선 가중치 EdgePropertyMap. 없으면 1로 간주.
  5. float_count: True이면 bin 카운트를 float 형으로 반환(정규화 등에 편리), False이면 정수형 카운트.

3. 반환값

  1. bin_counts: 2차원 numpy.ndarray. 각 (i,j) 셀에 “소스 속성이 i-bin에, 타깃 속성이 j-bin에 해당하는 간선 수(또는 가중치 합)”가 기록됨.
  2. source_bins: 소스 속성에 해당하는 bin 경계
  3. target_bins: 타깃 속성에 해당하는 bin 경계

4. 간단 예시 1: 무작위 그래프에서 out-degree vs. out-degree 히스토그램

아래 코드는 예제로 무작위 그래프(probabilistic-configuration 모델)를 생성한 뒤, 소스노드의 out-degree와 타깃노드의 out-degree의 상관히스토그램을 구합니다.

# corr_hist_tutorial_1.py

import graph_tool.all as gt
import numpy as np
import matplotlib.pyplot as plt
from math import sin, pi

def sample_k(max_k):
    """
    예시 용도: 1~max_k 사이 정수 k 중,
    1/k 확률로 승인(accept)하는 간단한 난수 샘플
    """
    while True:
        k = np.random.randint(1, max_k+1)
        if np.random.random() < 1.0 / k:
            return k

def main():
    # 1) 무작위 그래프 생성
    #    - 노드 수: 10000
    #    - degree 생성함수: sample_k(40) => 대략 높은 차수는 적게, 낮은 차수는 상대적 빈도가 높게
    #    - model="probabilistic-configuration"
    #    - edge_probs(...)는 i,j 노드 쌍 연결 확률
    #      (단순 예시로 sin(i/pi)*sin(j/pi) + 1 / 2 형태)
    g = gt.random_graph(
        10000,
        lambda: sample_k(40),
        model="probabilistic-configuration",
        edge_probs=lambda i, j: (sin(i/pi)*sin(j/pi) + 1)/2,
        directed=False,
        n_iter=100
    )

    # 2) corr_hist 계산: 소스=out-degree, 타깃=out-degree
    #    bins는 예시로 [ [0, 50, 1], [0, 50, 1] ] => 0부터 50까지 1단위
    #    (실제로 차수가 50 넘어갈 수도 있지만 예시로 가정)
    bins = [[0, 50, 1], [0, 50, 1]]
    bin_counts, src_bins, tgt_bins = gt.corr_hist(
        g,
        deg_source="out",
        deg_target="out",
        bins=bins,
        weight=None,
        float_count=True
    )

    # 3) 결과 시각화
    plt.figure(figsize=(6,5))
    # bin_counts.T로 전치한 이유: 이미지 표시 시,
    # x축=소스, y축=타깃으로 두기 위해
    plt.imshow(bin_counts.T, origin="lower", interpolation="nearest")
    plt.xlabel("Source out-degree bin")
    plt.ylabel("Target out-degree bin")
    plt.title("Out-degree vs. Out-degree correlation histogram")
    plt.colorbar(label="Count")
    plt.tight_layout()
    plt.savefig("corr_hist_out_out.png")
    plt.show()

if __name__ == "__main__":
    main()

코드 설명

  1. sample_k(max_k): 무작위로 차수를 뽑는 간단한 예시 함수(높은 k가 낮은 확률로 선택되도록).
  2. gt.random_graph(...):
    • node 수 10000
    • 주어진 차수 분포(확률적 설정) + 간선 연결 확률로 그래프 생성
  3. corr_hist 호출 시,
    • deg_source="out", deg_target="out" → 소스·타깃 모두 out-degree
    • bins=[[0,50,1],[0,50,1]] → 0부터 50까지 1단위 구간으로 bin화
    • 결과: (bin_counts, src_bins, tgt_bins)
  4. 시각화:
    • plt.imshow(bin_counts.T, ...)로 2D 히트맵처럼 그림
    • (i, j) 픽셀이 “소스 degree i bin” vs “타깃 degree j bin”에 해당하는 간선 수(또는 가중치 합)를 표현

5. 간단 예시 2: 노드 속성(VertexPropertyMap) 기반 히스토그램

이번에는 네트워크가 준비되어 있고, 노드마다 어떤 “실수” 속성을 가정하겠습니다. 가령, 노드별 무작위 값(0~1)을 소스·타깃 속성으로 해서 그 상관을 히스토그램으로 본다면, 대체로 균등하게 분포되리라 예상됩니다.

# corr_hist_tutorial_2.py

import graph_tool.all as gt
import numpy as np
import matplotlib.pyplot as plt

def assign_random_property(g):
    """
    그래프의 각 노드에 0~1 난수를 할당
    """
    prop = g.new_vertex_property("double")
    for v in g.vertices():
        prop[v] = np.random.rand()
    return prop

def main():
    # 예시 그래프
    g = gt.collection.data["pgp-strong-2009"]  # graph-tool 내장 예시
    
    # 무작위 속성 할당
    rand_prop_1 = assign_random_property(g)
    rand_prop_2 = assign_random_property(g)
    
    # bin 범위 지정 (0부터 1까지 0.05 간격)
    bins = [
        [0.0, 1.0, 0.05],  # 소스 속성 bin
        [0.0, 1.0, 0.05]   # 타깃 속성 bin
    ]
    
    # corr_hist
    bin_counts, s_bins, t_bins = gt.corr_hist(
        g,
        deg_source=rand_prop_1,
        deg_target=rand_prop_2,
        bins=bins,
        weight=None,
        float_count=True
    )
    
    # 시각화
    plt.figure(figsize=(6,5))
    plt.imshow(bin_counts.T, origin="lower", interpolation="nearest")
    plt.xlabel("rand_prop_1 (source) bins")
    plt.ylabel("rand_prop_2 (target) bins")
    plt.title("Random property correlation histogram")
    plt.colorbar(label="Count")
    plt.tight_layout()
    plt.savefig("corr_hist_random_props.png")
    plt.show()

if __name__ == "__main__":
    main()

해설

  • rand_prop_1, rand_prop_2: 서로 독립인 0~1 난수 → 소스 vs 타깃 스칼라
  • bin 범위를 [0.0, 1.0, 0.05] → 자동으로 (1.0 - 0.0)/0.05 = 20개 구간
  • 시각화 결과: 거의 고르게 분포된 2D 히스토그램(특별한 패턴 없음)

6. bins 설정 팁

  • bins=[[start, stop, step], [start, stop, step]] 형태로 주면, 시작~끝 사이를 step 간격으로 잘라 bin을 자동 생성.
  • 만약 bins=[[0,1],[0,1]] (기본값)처럼 리스트 크기가 2이면, 내부적으로 더 세밀한 로직에 따라 bin 설정(0~1 범위 10등분 등)될 수 있음.
  • 차수처럼 최대값이 커질 수 있는 경우, 그래프 자료를 사전에 조사하여 최대 차수 등을 구하고 그 범위에 맞춰 bin을 설정하는 것이 좋습니다.

7. 가중치(Edge weights) 고려

weight= 인자로 간선 EdgePropertyMap을 주면, 단순 “간선 개수”를 세는 대신, “가중치 합”으로 계산됩니다. 예를 들어, 간선이 교통량이나 이동 빈도를 나타낸다면, 히스토그램 값은 “두 노드 속성 bin에 해당하는 (소스, 타깃) 쌍에 대한 교통량 총합”이 됩니다.

def assign_edge_weights(g):
    w_prop = g.new_edge_property("double")
    for e in g.edges():
        w_prop[e] = np.random.uniform(1, 5)
    return w_prop

def weighted_corr_hist_example():
    g = gt.collection.data["pgp-strong-2009"]
    w_prop = assign_edge_weights(g)
    bins = [[0, 50, 5], [0, 50, 5]]  # 0~50, 5단위로 bin
    bin_counts, s_bins, t_bins = gt.corr_hist(
        g,
        deg_source="out",
        deg_target="out",
        bins=bins,
        weight=w_prop,
        float_count=True
    )
    # 이제 bin_counts는 "소스 out-degree, 타깃 out-degree" 쌍에 대한 간선 가중치 합

8. 결과 해석 및 활용 아이디어

  1. 히트맵(heatmap) 시각화
    • x축(소스 속성), y축(타깃 속성), 색상(간선 수 또는 가중치 합) → 직관적으로 어느 구간(속성 범위)들이 많이 연결되어 있는지 확인 가능.
  2. 혼배(assortativity)와 연계
    • corr_hist로 얻은 2D 히스토그램을 통해서도 대략 양/음의 상관(동질혼배, 이질혼배) 경향을 볼 수 있고,
    • 더 정확한 수치화는 assortativity 또는 scalar_assortativity 함수를 병행.
  3. 도시·교통 응용
    • 교차로(노드)마다 “연속형 지표”(교통량, 평균 대기시간 등)를 가정 → 인접 교차로와의 상관 패턴을 2D 히스토그램으로 살펴볼 수 있음.
    • 예) 고트래픽(혼잡) 교차로들이 역시 고트래픽 교차로와 연결 많은지(동질혼배), 아니면 주로 저트래픽 구간과 연결되는지(이질혼배).
  4. 가중치:
    • 실제 교통 데이터(도로 용량, 차량흐름량 등)을 간선 가중치로 두면, 해당 상관 패턴을 “총 교통량” 관점에서 더욱 정확히 파악 가능.

9. 요약 정리

  • corr_hist 함수: 네트워크에서 (소스노드 속성, 타깃노드 속성) 쌍에 대한 분포(히스토그램)을 계산.
  • 매개변수
    • deg_source, deg_target: 차수 타입(in/out/total) 또는 노드 속성의 VertexPropertyMap.
    • bins: 2차원 bin 경계 지정.
    • weight: 간선 가중치 반영 가능.
    • float_count: True일 시 bin_counts를 float으로 반환(정규화 등에 편리).
  • 결과: (bin_counts, source_bins, target_bins)
    • bin_counts는 2D 배열로, (i,j) 위치가 “소스 i-bin vs 타깃 j-bin”에 해당하는 연결(또는 가중치 합).
  • 활용:
    • 혼배(assortativity) 시각적 파악, 노드 속성 간 연결 패턴 분석, 교통/사회/생물/기술망 등에서 특정 속성의 상관성 발견.

이상으로 graph-tool의 corr_hist 함수를 사용해 네트워크 상에서 노드 속성의 2차원 상관관계를 히스토그램 형태로 뽑아내고, 이를 시각화·해석하는 방법을 살펴보았습니다. 이 튜토리얼이 초보자 분들께 도움이 되길 바라며, 다양한 도시·교통, 사회적 데이터 등에 응용해 보시기를 권장합니다. 즐거운 네트워크 분석 되세요!


아래 튜토리얼은 graph-tool 라이브러리의 combined_corr_hist 함수를 통해, 단일 노드(single-vertex) 관점에서 두 가지 속성(예: in-degree와 out-degree, 혹은 임의의 두 VertexPropertyMap)이 어떻게 동시에 분포하는지 2차원 히스토그램 형태로 계산하고 시각화하는 방법을 상세하게 설명합니다. 초보자도 쉽게 접근할 수 있도록 친절한 한글 해설과 함께, 예시 파이썬 코드를 제시했습니다.


1. combined_corr_hist 함수란?

combined_corr_hist(g, deg1, deg2, bins=[[0,1],[0,1]], float_count=True) 는,

  • 네트워크의 단일 노드에서 측정한 두 가지 속성(예: in-degree와 out-degree, 또는 임의 스칼라 속성 deg1, deg2)에 대해,
  • 그 모든 노드가 가지는 (deg1, deg2) 쌍이 얼마나 많이 출현하는지(혹은 몇 개 노드가 그러한 쌍을 보이는지)를 2차원 히스토그램(bin_counts)으로 만들어 줍니다.

즉, 이웃 간의 상관을 보는 corr_hist와 달리, 단일 노드 기준으로 두 속성을 동시에 binning하여 그 빈도(또는 가중치)를 계산한다는 것이 중요한 차이점입니다.


2. 주요 파라미터

  1. g: Graph 객체
  2. deg1, deg2:
    • 문자열 "in", "out", "total" 중 하나를 지정(노드 차수)
    • 또는 VertexPropertyMap(노드별 임의 스칼라 속성)
    • 예) "in""out"을 사용하면 “각 노드의 (in-degree, out-degree) 분포”를 볼 수 있음.
  3. bins:
    • 2차원 히스토그램의 구간 경계를 지정하는 리스트. [ [deg1_bins], [deg2_bins] ] 형식.
    • 각 리스트 크기가 2이면, [start, step] 처럼 자동 bin 생성 규칙으로 사용.
  4. float_count:
    • True면 bin count를 float으로 반환(정규화 등에 유리),
    • False면 bin count는 정수형.

3. 반환값

  1. bin_counts: 2차원 NumPy 배열. (i, j) 위치가 “deg1가 i번째 bin, deg2가 j번째 bin에 해당하는 노드들의 수”를 의미.
  2. first_bins: deg1의 bin 경계 (NumPy 배열)
  3. second_bins: deg2의 bin 경계 (NumPy 배열)

4. 예시 1: 무작위 그래프에서 (in-degree, out-degree) 히스토그램

다음 예제 코드는 랜덤 그래프(10000개의 노드, 각 노드의 in/out 차수를 임의 생성)를 만든 뒤, combined_corr_hist(g, "in", "out")각 노드의 (in-degree, out-degree) 쌍이 어떻게 분포하는지 확인합니다.

# combined_corr_hist_tutorial_1.py

import graph_tool.all as gt
import numpy as np
import matplotlib.pyplot as plt
from math import sin, pi

def sample_k(max_k):
    """
    예시: (in_k, out_k) 형태로 생성
    sin(i/pi)*sin(j/pi) + 1)/2 의 확률로 accept
    """
    accept = False
    while not accept:
        i = np.random.randint(1, max_k + 1)
        j = np.random.randint(1, max_k + 1)
        # 임의 조건으로 accept 결정
        accept = np.random.random() < (sin(i / pi) * sin(j / pi) + 1) / 2
    return i, j  # (in-degree, out-degree)

def main():
    # 1) 무작위 그래프 생성
    #    노드수=10000, sample_k(40)을 통해 (in_k, out_k) 분포
    g = gt.random_graph(
        10000,
        lambda: sample_k(40)  # 각 노드의 (in_degree, out_degree) 할당
    )
    
    # 2) (in-degree, out-degree) 히스토그램 계산
    #    bins는 예시로 [ [0, 40, 1], [0, 40, 1] ]
    #    => deg1= 0~40, deg2= 0~40, 간격 1
    bins = [[0, 40, 1], [0, 40, 1]]
    bin_counts, first_bins, second_bins = gt.combined_corr_hist(
        g, deg1="in", deg2="out", bins=bins, float_count=True
    )
    
    # 3) 시각화
    plt.figure(figsize=(6,5))
    # (i, j) => i= in-degree bin, j= out-degree bin
    plt.imshow(bin_counts.T, origin="lower", interpolation="nearest")
    plt.xlabel("In-degree bin")
    plt.ylabel("Out-degree bin")
    plt.title("In-degree vs. Out-degree combined histogram")
    plt.colorbar(label="Count of nodes")
    plt.tight_layout()
    plt.savefig("combined_in_out_hist.png")
    plt.show()

if __name__ == "__main__":
    main()

코드 해설

  1. sample_k(max_k): 노드마다 (in_k, out_k) 쌍을 랜덤 생성.
  2. gt.random_graph(...): 위에서 생성한 (in_k, out_k)를 각 노드의 타겟 차수로 사용해 그래프를 구성.
  3. combined_corr_hist(g, "in", "out"): 노드 단위로 (in-degree, out-degree)가 몇인 노드가 몇 개나 있는지, 2D 히스토그램을 얻음.
  4. 시각화 시, x축이 in-degree bin, y축이 out-degree bin. bin_counts[i, j] = “in-degree가 i-bin, out-degree가 j-bin인 노드 수”.

5. 예시 2: 임의 VertexPropertyMap 2개를 이용한 히스토그램

이번에는 차수가 아니라 노드별로 두 가지 임의 속성(예: prop1, prop2)을 할당하고, 그 조합 분포를 살펴봅니다. 간단히 0~1 사이 난수 두 개를 만든다고 합시다.

# combined_corr_hist_tutorial_2.py

import graph_tool.all as gt
import numpy as np
import matplotlib.pyplot as plt

def assign_random_property(g):
    """
    각 노드에 0~1 범위 난수를 할당
    """
    prop = g.new_vertex_property("double")
    for v in g.vertices():
        prop[v] = np.random.rand()
    return prop

def main():
    # 예시 그래프 로드 (pgp-strong-2009)
    g = gt.collection.data["pgp-strong-2009"]
    
    # 두 가지 속성 생성
    prop1 = assign_random_property(g)  # 예: rand in [0,1]
    prop2 = assign_random_property(g)  # 예: rand in [0,1]
    
    # bins 설정: 0~1 범위를 0.05 간격으로
    bins = [[0.0, 1.0, 0.05], [0.0, 1.0, 0.05]]
    
    # combined_corr_hist
    bin_counts, first_bins, second_bins = gt.combined_corr_hist(
        g, deg1=prop1, deg2=prop2, bins=bins, float_count=True
    )
    
    # 시각화
    plt.figure(figsize=(6,5))
    plt.imshow(bin_counts.T, origin="lower", interpolation="nearest")
    plt.xlabel("prop1 bin")
    plt.ylabel("prop2 bin")
    plt.title("Random properties combined histogram")
    plt.colorbar(label="Count of nodes")
    plt.tight_layout()
    plt.savefig("combined_random_props.png")
    plt.show()

if __name__ == "__main__":
    main()

해설

  • prop1, prop2 각각 독립 난수 → (prop1, prop2) 쌍이 골고루 분포하는 2D 히스토그램 예상.
  • bin은 [0.0, 1.0, 0.05] → 0부터 1까지 step=0.05, 총 20개 구간.

6. bins 설정 주의사항

  • bins=[[start, stop, step], [start, stop, step]] 구조로 주면, 자동으로 (stop - start)/step 개의 bin 구간을 만든다.
  • 만약 차수와 같이 최대값이 큰 경우, 실제 노드 데이터 범위를 미리 파악한 뒤 해당 범위에 맞게 bin을 설정.
  • [ [0,1], [0,1] ]처럼 리스트 길이가 2면 기본값(작은 히스토그램)으로 잡힐 수 있으므로, 실제분포에 따라 적절히 바꾸는 것이 좋다.

7. float_count 옵션

  • float_count=Truebin_counts가 float형. 추후 정규화(전체 노드 수로 나눔 등)를 하거나, 여러 후속 계산에서 유리.
  • float_count=False → bin_counts가 unsigned integer형(노드 ‘개수’를 그대로 사용).
    • 대규모 그래프에서 빠른 정수 연산이 필요하면 고려.

8. 응용 및 해석

  1. (in-degree vs. out-degree) 분포
    • 보통 무방향 그래프면 in=out이나, 방향성이 있는 네트워크(도로교통, 웹 등)에서는 in/out 차이가 있을 수 있음.
    • 예) “대도시(노드)의 유입도로 수(in-degree)가 많으면서, 동시에 유출도로 수(out-degree)도 많은지?”
  2. 임의 속성 2개 → 노드별로 수집된 통계 지표(인구, 상업지수 등)를 결합하여 2D 분석 가능.
  3. 분산 구조 파악: combined_corr_hist 결과를 heatmap으로 시각화하면, 어느 구간들이 노드가 몰려 있는지 직관적으로 확인할 수 있음.
  4. 전처리: 필요에 따라 속성값을 log-scale 등으로 변환 후 binning하기도 함.

9. 정리

  • combined_corr_hist: 노드마다 두 속성(deg1, deg2) 을 binning → 2D 히스토그램(얼마나 많은 노드가 특정 (deg1, deg2) 구간에 있는지)
  • 사용 예시:
    1. "in" vs. "out"으로 노드 차수 분포 구조 파악
    2. 임의 VertexPropertyMap 2개에 대해 노드별 조합 시각화
  • 결과: (bin_counts, first_bins, second_bins)
    • bin_counts[i, j] = “deg1가 i번째 bin, deg2가 j번째 bin에 해당하는 노드 수”
    • 시각화: imshow(bin_counts.T, ...), x축=deg1 bin, y축=deg2 bin
  • :
    • bin 범위/간격을 실제 데이터 범위에 맞춰 설정
    • float_count=True로 놓으면 후속 작업(정규화/분석)에 편리

이처럼 combined_corr_hist는 노드 관점에서 두 가지 속성의 분포를 한눈에 파악할 수 있는 유용한 함수입니다. 도로·교통 네트워크, 도시 빅데이터 맥락에서도, 예를 들어 “교차로의 (유입 교통량, 유출 교통량)”을 한데 분석하거나, “인구밀도 vs. 차량혼잡도” 등 다양한 조합에 응용하시면, 더 풍부한 인사이트를 얻을 수 있을 것입니다. 즐거운 네트워크 분석 되세요!

아래 튜토리얼은 graph-tool 라이브러리에서 제공하는 avg_neighbor_corr 함수를 사용하여, “특정 노드 속성(예: 차수)이 특정 구간(bin)에 있을 때, 그 노드의 이웃들이 가지는 또 다른 속성(또는 같은 속성)의 평균값”을 구하는 방법을 단계별로 살펴봅니다. 이 함수는 기본적으로 “평균 인접노드 특성”을 구해주는 툴이므로, 네트워크에서 노드가 특정 수준의 속성을 가질 때 그 이웃들은 어떠한 분포를 갖는지 파악할 때 유용합니다. 초보자도 쉽게 따라 할 수 있도록 코드 예시, 한글 주석을 상세히 포함하였습니다.


1. avg_neighbor_corr 함수란?

avg_neighbor_corr(g, deg_source, deg_target, bins=[0, 1], weight=None)
  • 기본 개념:

    • 노드마다 deg_source라는 스칼라 속성(차수, 혹은 사용자 정의 VertexPropertyMap)이 있음.
    • 그 노드의 이웃들이 가진 deg_target 속성값을 평균 내는 과정.
    • 그런 뒤, deg_source에 따라 여러 구간(bin)으로 나누어, 각 bin 별로 “이웃의 평균 deg_target”을 계산해주는 함수.
  • 매개변수

    1. g: 그래프 객체(Graph).
    2. deg_source: 문자열(“in”, “out”, “total”) 또는 VertexPropertyMap.
    3. deg_target: 동일하게 노드의 다른(혹은 같은) 스칼라 속성 정의.
    4. bins: deg_source 값을 구간별로 나눌 때 사용하는 bin 설정.
      • 리스트 크기가 2라면 [start, width]로 간주해, start부터 일정 간격(width)로 자동 binning.
      • 직접 bin 경계값 목록을 지정할 수도 있음(예: [0, 10, 20, 30]).
    5. weight: EdgePropertyMap (간선 가중치). 없으면 가중치=1로 가정.
  • 반환값

    1. bin_avg: 각 bin(= deg_source 구간)에 해당하는 노드들의 이웃 deg_target 평균값.
    2. bin_dev: 표준편차(standard deviation).
    3. bins: 최종적으로 사용된 bin 경계 배열.

2. 동작 방식 개요

  1. 각 노드 (v)의 (\text{deg_source}[v]) 값을 보고, 그 노드가 어느 bin에 속하는지 결정.
  2. 해당 노드 (v)가 가진 이웃(간선으로 연결된 노드들)의 (\text{deg_target}) 값을 평균 냄.
  3. 같은 bin에 속하는 노드들의 이웃평균을 다시 전체적으로 평균 낸 값이 (\text{bin_avg}).
    • 표준편차도 함께 계산((\text{bin_dev})).

이로써 “소스 속성이 특정 구간에 있는 노드들은, 이웃들의 타깃 속성 평균이 얼마 정도인지”를 bin별로 알 수 있습니다.


3. 간단 예시: 무작위 그래프 (out-degree vs. out-degree)

아래 코드는 graph-tool의 random_graph 함수를 사용해 1만 노드 정도를 갖는 랜덤 그래프를 생성한 뒤, 소스=out-degree에 따라 binning하고, 각 bin에 속한 노드들이 갖는 이웃들의 out-degree 평균을 구합니다.

# avg_neighbor_corr_tutorial_1.py

import graph_tool.all as gt
import numpy as np
import matplotlib.pyplot as plt
from math import sin, pi

def sample_k(max_k):
    """
    예시 용 함수:
    1~max_k 범위에서 난수 k를 뽑되,
    '1/k 확률'로 accept하는 간단한 구조
    """
    accept = False
    while not accept:
        k = np.random.randint(1, max_k + 1)
        # 예: 1/k 확률로 채택
        accept = np.random.random() < 1.0 / k
    return k

def main():
    # 1) 무작위 그래프 생성
    g = gt.random_graph(
        10000,
        lambda: sample_k(40),
        model="probabilistic-configuration",
        edge_probs=lambda i, j: (sin(i / pi) * sin(j / pi) + 1)/2,
        directed=False,
        n_iter=100
    )
    
    # 2) avg_neighbor_corr
    #    - deg_source="out": 소스 노드의 out-degree
    #    - deg_target="out": 이웃 노드의 out-degree
    #    - bins=[0, 5] => 0부터 시작, bin width=5로 계속
    #      (실제로 얼마나 많이 생길지에 따라 조정 필요)
    bin_avg, bin_dev, bins = gt.avg_neighbor_corr(
        g,
        deg_source="out",
        deg_target="out",
        bins=[0, 5],
        weight=None
    )
    
    # bin_avg: bins의 각 구간에 해당하는 노드들에 대해, 이웃의 out-degree 평균
    # bin_dev: 표준편차
    
    # 3) 결과 시각화
    #   bins는 bin 경계이므로, len(bins)-1 개 구간
    x_vals = (bins[:-1] + bins[1:]) / 2.0  # 구간 중앙값
    y_vals = bin_avg
    y_errs = bin_dev
    
    plt.figure(figsize=(6,4))
    plt.errorbar(x_vals, y_vals, yerr=y_errs, fmt='o', capsize=3)
    plt.xlabel("Source out-degree bin (center)")
    plt.ylabel("Neighbor out-degree (mean)")
    plt.title("Average neighbor out-degree vs. source out-degree")
    plt.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.savefig("avg_neighbor_out_out.png")
    plt.show()

if __name__ == "__main__":
    main()

코드 해설

  1. 무작위 그래프: 1만 노드, sample_k(40) 함수로 (약간 편향된) 차수 분포 생성.
  2. gt.avg_neighbor_corr(...) 호출 파라미터:
    • deg_source="out", deg_target="out", 즉 같은 속성(노드 out-degree).
    • bins=[0, 5]: 0부터 시작, bin 폭 5씩 쪼개 (0~5,5~10,10~15, …)
  3. 반환값 (bin_avg, bin_dev, bins):
    • bin_avg[i]: bins의 i번째 구간 소속 노드들의 이웃 out-degree 평균.
    • bin_dev[i]: 그 표준편차.
    • bins: 최종 bin 경계값 배열.
  4. 시각화:
    • x축: bin의 중앙값
    • y축: 이웃 out-degree 평균
    • 오차막대(yerr)로 표준편차 표현.

4. 예시 2: 노드 속성(VertexPropertyMap) 기반

이번엔 노드별로 임의의 스칼라 속성(예: 속도, 인구 등)을 가진다고 치고, 그 이웃들의 또 다른 속성(혹은 같은 속성)의 평균을 본다고 합시다. 코드는 다음과 같습니다:

# avg_neighbor_corr_tutorial_2.py

import graph_tool.all as gt
import numpy as np
import matplotlib.pyplot as plt

def assign_random_property(g, low=0.0, high=100.0):
    """
    각 노드에 [low, high] 범위에서 임의 실수 속성 할당
    """
    prop = g.new_vertex_property("double")
    for v in g.vertices():
        prop[v] = np.random.uniform(low, high)
    return prop

def main():
    # 예시 그래프 로드
    g = gt.collection.data["pgp-strong-2009"]
    
    # 속성 1: 예) node_inhabitants(거주민 수/인구 등 가정)
    pop_prop = assign_random_property(g, 1.0, 5000.0)
    
    # 속성 2: 예) node_income(가구소득 등, 가정)
    income_prop = assign_random_property(g, 1000.0, 50000.0)
    
    # bins 설정: [start, step], 여기서는 [0, 1000] => 0에서 시작, 폭=1000
    # 실제 데이터 범위는 1~5000 정도이므로
    # bin은 대략 (0-1000), (1000-2000), (2000-3000), (3000-4000), (4000-5000) ...
    bins = [0, 1000]
    
    # avg_neighbor_corr
    #   - deg_source=pop_prop  => 소스 노드 인구
    #   - deg_target=income_prop => 타깃(이웃) 노드 소득
    bin_avg, bin_dev, final_bins = gt.avg_neighbor_corr(
        g,
        deg_source=pop_prop,
        deg_target=income_prop,
        bins=bins,
        weight=None
    )
    
    # 시각화
    # bin_avg: 각 인구 bin에 해당하는 노드들이 가진 이웃들의 소득 평균
    x_vals = (final_bins[:-1] + final_bins[1:]) / 2
    y_vals = bin_avg
    y_errs = bin_dev
    
    plt.figure(figsize=(6,4))
    plt.errorbar(x_vals, y_vals, yerr=y_errs, fmt='o', capsize=3)
    plt.xlabel("Node population bin")
    plt.ylabel("Neighbor income (avg)")
    plt.title("Average neighbor income vs. node population")
    plt.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.savefig("avg_neighbor_pop_income.png")
    plt.show()

if __name__ == "__main__":
    main()

해석

  • x축 bin: 노드 인구(population) 구간
  • y축: 그 노드 이웃들의 평균 소득(income)
  • “인구가 많은 노드에 연결된 이웃 노드들의 평균 소득이 높은지/낮은지”를 시각적으로 파악할 수 있음.

5. bins 설정 주의

  • [start, step] 형태를 주면, 시작점부터 특정 간격(step)으로 binning. 실제 데이터 범위보다 더 넓은 구간을 할당하거나, 너무 좁으면 bin 경계 바깥쪽 노드들이 무시될 수 있음.
  • 만약 정확한 경계 목록을 알고 있으면 [0, 10, 20, 30, ...]처럼 구체적 리스트를 주어도 됨.

6. 활용: 도시·교통 빅데이터 맥락

  • 소스 속성: 교차로(노드)의 교통량, 혼잡도, 인구밀도 등
  • 타깃 속성: 이웃 교차로들의 평균 차선 수, 평균 지연시간, 평균 상업지수 등
  • 예) “교통량이 높은 교차로에 인접한 교차로들의 평균 교통량(혹은 평균 상업지수)은 어떠한가?”
    • 혼잡도가 높은 지점끼리 모여 있으면 양의 상관성을 보여줄 것이고, “병목 구간” 파악 등 정책적 시사점을 얻음.

7. 반환값 해석 요령

  1. bin_avg: 각 bin(소스 속성 구간)에 대한 이웃 속성 평균.
    • 수치가 높으면 “해당 소스 구간 노드들이 이웃과 함께 높은 (\text{deg_target})을 가진다”는 뜻.
  2. bin_dev: 표준편차
    • 값이 큰 bin은 “노드들이 이웃 속성 측면에서 편차가 크다”는 것을 의미.
  3. bins: 최종 사용된 bin 경계
    • x축 plotting 시 center값( ((\mathrm{bin}{i} + \mathrm{bin}{i+1})/2) )을 많이 사용.

8. 요약 정리

  • avg_neighbor_corr:
    • 노드를 “소스 속성(bin 구간)”으로 그룹핑 → 각 그룹 노드들의 이웃이 가진 “타깃 속성”의 평균을 구함.
  • 반환:
    • bin_avg(평균), bin_dev(편차), bins(구간 경계)
  • 해석:
    • x축: 소스 속성(bin 구간),
    • y축: 이웃 타깃 속성의 평균 → “소스 속성이 높아질수록 이웃의 타깃 속성도 높아지는지(양의 경향), 그렇지 않은지(무관 or 음의 경향) 등”을 쉽게 파악.
  • 도시·교통:
    • 교차로별 교통량/혼잡도(소스) vs. 이웃 교차로들의 교통량/혼잡도(타깃),
    • 또는 인구 vs. 이웃의 상업지수, 소득 vs. 이웃의 인프라 수준 등 다양한 조합으로 적용 가능.

이로써, 특정 특성(bin)에 속하는 노드들의 이웃 특성 평균을 살펴보는 avg_neighbor_corr 함수를 활용하는 방법, 그리고 그 결과를 시각화·해석하는 간단한 튜토리얼을 마칩니다. 이 분석법은 네트워크 상에서 “특정 값이 큰 노드들이, 과연 유사한(높은) 이웃 노드를 갖는가, 아니면 그렇지 않은가?”를 간단 명료하게 보여주므로, 혼배(assortativity) 현상이나 정책적 우선순위 결정에 있어 큰 도움을 줄 수 있습니다. 즐거운 네트워크 분석 되시길 바랍니다!

profile
AI가 재밌는 걸

0개의 댓글