QGIS 기반 공간통계

인접지역 판단 거리에 변화에 따른 Moran’s I 통계량 그래프 그리기

앞에 분석해 본 코드는 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

댓글

댓글 본문
작성자
비밀번호
  1. 소스가 짤린거같아요 ㅠㅠ
버전 관리
BJ Jang
현재 버전
선택 버전
graphittie 자세히 보기