앞에 분석해 본 코드는 PySAL의 기본 샘플에 비해 엄청나게 길어 졌지만, 결과로 딸랑 통계량 하나만 나오는 것은 차이가 없다. 어짜피 Gloval Moran’s I 라는 것이 통계량 하나를 만들어 그 지역의 자기상관성을 파악해 보는 것이긴 하지만 좀 아쉽다.
또한 인접을 판단하는 기준으로 정했던 100Km(100000)라는 거리가 과연 의미가 있는지도 의문이다.
그러면 좀더 수정을 해서 인접을 판단하는 거리를 변화시켜 가며 Moran’s I 값이 어찌 변화되는 지를 좀 더 시각적으로 알아보자.
이를 위해 수정한 소스는 다음과 같다.
# coding=utf-8 if not iface: iface = qgis.gui.QgisInterface()
from pysal import W, Moran import numpy as np import qgis from qgis.core import * from qgis.gui import QgsMessageBar from PyQt4.QtGui import QProgressBar from PyQt4.QtCore import * import matplotlib.pyplot as plt
# 전역변수 설정 FROM_DIST = 10000 TO_DIST = 200000 BY_DIST = 10000 NAME_FIELD = "SGG" VALUE_FIELD = u"노인비율" CRITICAL_Z = 1.96
########################## # 레이어에서 정보 추출
# 레이어 선택 oLayer = iface.activeLayer() if not oLayer: raise UserWarning(u"레이어를 먼저 선택해야 합니다.") # 종료
layerName = oLayer.name() layerType = oLayer.geometryType() crs = oLayer.crs()
# ID 리스트 확보 oIDs = oLayer.allFeatureIds()
# Progress 생성 progressMessageBar = iface.messageBar().createMessage(u"레이어 정보 수집중...") progress = QProgressBar() progress.setMaximum(len(oIDs)) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) iface.messageBar().pushWidget(progressMessageBar, iface.messageBar().INFO)
# centroid,value(y),name 모으기 centroidList = [] dataList = [] nameList = [] for i, oID in enumerate(oIDs): progress.setValue(i)
iFeature = oLayer.getFeatures(QgsFeatureRequest(oID)).next() iGeom = iFeature.geometry().centroid() centroidList.append(iGeom) data = iFeature[VALUE_FIELD] dataList.append(data) name = iFeature[NAME_FIELD] nameList.append(name)
# 통계 대상 값 수집 y = np.array(dataList)
####################### # FROM_DIST에서 TO_DIST까지 BY_DIST 씩 거리 증가하며 Moran's I 구하기
# 전체 몇 번 돌아가야 하는지 계산 totalCnt, mod = divmod((TO_DIST-FROM_DIST), BY_DIST) totalCnt += 1 progress.setMaximum(totalCnt)
# 거리를 늘려가며 반복하며 Moran's I 계산 miResults = {} for i, testDist in enumerate(range(FROM_DIST, (TO_DIST+BY_DIST), BY_DIST)): progress.setValue(i)
# Weight Matrix 계산 위한 정보 수집 neighbors = {} weights = {} for iID, iCent in zip(oIDs, centroidList): iRowNeighbors = [] iRowWeights = [] for jID, jCent in zip(oIDs, centroidList): # 동일 지역인 경우 제외 if iID == jID: continue # 기준거리 이내인 경우 인접한 것으로 기록 dist = iCent.distance(jCent) if |