본문 바로가기

배운 책들 정리/공공데이터로 배우는 R 데이터 분석 with 샤이니

공공데이터 with 샤이니 7,8 - 분석 주제를 지도로 시각화하기, 통계 분석과 시각화

1. 분석 주제를 지도로 시각화하기 CP 7 

1) 우리 동네가 옆 동네보다 비쌀까? : 데이터 불러오기

# 3. 우리 동네가 옆 동네보다 비쌀까?
# 특정 지역의 평균 가격을 주변 지역과 비교
# 평당 가격(py) 평균 값을 모든 지도에 표시
# 마커스 클러스터링 = 지도에 표시되는 마커가 너무 많을 때, 특정한 기준으로 하나의 클러스터로 묶어주는 방법


# 데이터 불러오기 ----- 
# 데이터 준비
# 아파트 가격
load("./data/apt_price.rdata")
head(apt_price)
# 최고가 레스터 데이터
load("./data/apt_high.rdata")
head(apt_high)
# 급등한 지역 레스터 데이터
load("./data/apt_hot.rdata")
head(apt_hot)
# 서울시 1km 그리드 데이터
library(sf)
grid <- st_read("./data/sigun_grid/seoul.shp")
# 서울시 경계선 데이터
bnd <- st_read ("./data/sigun_grid/seoul.shp")

# 데이터 불러오기 -----

2) 우리 동네가 옆 동네보다 비쌀까? : 마커 클러스터링 옵션 설정

# 마커 클러스터링 옵션 설정
# 상위 10%, 하위 10%, 나머지
q10 <- quantile(apt_price$py, probs=seq(.1,.9, by=.1))
q10
# 상위 10% = 90%
pct_90 <-  as.numeric(q10[9])
pct_90
# 상위 10% = 10%
pct_10 <-  as.numeric(q10[1])
pct_10
# 마커 클러스터링 함수 불러오기
load("./data/circle_marker/circle_marker.rdata")

3) 우리 동네가 옆 동네보다 비쌀까? : 마커 클러스터링 옵션 설정 2

# 색상 설정
circle.colors <- c()
# 마커 클러스터링 시각화
library(tidyverse)
library(leaflet)
leaflet() %>% 
  # 오픈스트리트맵
  addTiles() %>% 
  # 서울시 경계선
  addPolygons(data = bnd,
              color = "black",
              fill = NA,
              weight = 5) %>% 
# 최고가 레스터 데이터
addRasterImage(raster_high,
               colors = colorNumeric(palette = c("blue", "green", "yellow", "red"),domain = values(raster_high), na.color="transparent"), opacity = 0.4) %>% 
  # 급등 지역 레스터 데이터
  addRasterImage(raster_hot,
                 colors = colorNumeric(palette = c("blue", "green", "yellow", "red"),domain = values(raster_hot), na.color="transparent"), opacity = 0.4) %>% 
 # 체크 박스
addLayersControl(baseGroups = c("High Price in 2021", "Hot Price in 2021"), options = layersControlOptions(collapsed = F)) %>% 
  # 마커 클러스터링
  addCircleMarkers(data = apt_price, 
                   # 경도
                   lng = unlist(map(apt_price$geometry,1)),
                   # 위도
                   lat = unlist(map(apt_price$geometry,2)),
                   fillColor = circle.colors,
                   weight = apt_price$py,
                   clusterOptions = markerClusterOptions(iconCreateFuntion=JS(avg.formula)))

 

2.통계 분석과 시각화 CP 8

1) 라이브러리 준비 & 데이터 준비

# 통계분석과 시각화
# 1. 관심 지역 선택
# 라이브러리 준비
install.packages(c("tmap","ggpmisc","ggfortify"))
library(tmap)
library(ggpmisc)
library(ggfortify)
library(sf)
library(tidyverse)
library(grid)
# 데이터 준비
# 아파트 가격
load("./data/raster_hot.rdata")
head(apt_price)
load("./data/raster_high.rdata")
head(raster_high)

2) 그리드 데이터

# 그리드 데이터
grid <- st_read("./data/sigun_grid/seoul.shp")
# 관심지역 그리드 찾기
# thematic maps : 지도 위에 라벨 값을 표현할 때 leaflet 보다 편하게 사용 가능 
tmap_mode("view")
# 그리드 그려보기
tm_shape(grid)+
  # 경계선
  tm_borders() +
  # 텍스트
  tm_text("ID", col = "blue") +
  # 최고가 레스터 데이터
  tm_shape(raster_high)+
  # 색상
  tm_raster(palette = c("blue","green","yellow","red"),
            alpha = .4) +
  # 배경 지도
  tm_basemap(server = c("OpenStreetMap"))
  
# 
# 관심지역 그리드 81963
# 아파트 가격 & 그리드 데이터 합치기
apt_price <- st_join(apt_price,grid,join=st_intersects)
head(apt_price)
# 통계 분석 시에는 일반 데이터프레임 사용이 더 편함
# geometry 삭제
apt_price <- apt_price %>% 
  st_drop_geometry()
  head(apt_price)

지도 데이터 오류 파악으로 다시 진행

3) 서울시 전체 데이터 & 관심지역 데이터 저장

# 서울시 전체 데이터 & 관심지역 데이터
all <- apt_price
sel <- apt_price %>%  filter(ID == 81963)
head(all)
head(sel)
# 저장
save(all, file="./data/all.rdata")
save(sel, file="./data/sel.rdata")

4) 확률밀도함수 : 변수 설정까지

# 확률밀도함수 => 선택한 지역의 아파트가 비싼가?
load("./data/all.rdata")
load("./data/sel.rdata")
# 데이터 분포 보기 => 히스토그램
hist(all$py)
hist(sel$py)
# 구간을 어떻게 설정하느냐에 따라서 분포가 달라짐
# 이러한 단점을 극복하기 위해 확률밀도함수 사용
max_all <- density(all$py)
max_sel <- density(sel$py)
head(max_all)
head(max_sel)
# x: 평당 가격
# y: 확률 = 상대도수
max_all <- max(max_all$y)
max_sel <- max(max_sel$y)
# y축 최대값 // y축에는 max_all 들어가야 함
plot_high <- max(max_all,max_sel)
plot_high
# 평균값
avg_all <- mean(all$py)
avg_sel <- mean(sel$py)
avg_all;avg_sel

5) 그래프로 표현

# 서울시 전체 지역 확률밀도함수 그리기
plot(density(all$py),
     ylim = c(0,plot_high),
     col = "blue",
     lwd = 2
     )
# 서울시 전체 지역 평균값 선 그리기
abline(v = avg_all, 
       col = "blue",
       lwd = 2,
       lty = 2)
# 평균값 텍스트 입력 
text(avg_all + avg_all*0.2, # x축 위치
     plot_high * 0.1, # y축 위치
     round(avg_all))

#
#

# 선택 지역 확률밀도함수 그리기
lines(density(sel$py),
     ylim = c(0,plot_high),
     col = "red",
     lwd = 2
)
# 서울시 선택 지역 평균값 선 그리기
abline(v = avg_sel, 
       col = "red",
       lwd = 2,
       lty = 2)
# 평균값 텍스트 입력 
text(avg_sel + avg_sel*0.2, # x축 위치
     plot_high * 0.1, # y축 위치
     round(avg_sel))

6) 회귀분석

# 회귀분석 : 지역의 아파트 가격이 일년에 얼마나 변하는지?
options(scipen = 99)
# 데이터준비
load("./data/all.rdata")
load("./data/sel.rdata")
head(all)
head(sel)
# 거래 연월일 변수의 타입을 날짜로 변환
str(all)
all$ymd <- as.Date(all$ymd, "%Y-%m-%d")
str(sel)
sel$ymd <- as.Date(sel$ymd, "%Y-%m-%d")

# 월별 평균 가격
# 서울시 전체 지역
all <- aggregate(all$py, list(floor_date(all$ymd, "month")), mean)
# 선택 지역
sel <- aggregate(sel$py, list(floor_date(sel$ymd, "month")), mean)
# 변수 이름 변경
head(all);head(sel)
colnames(all) <- c("month","all_py")
colnames(sel) <- c("month","sel_py") 
head(all);head(sel)

7) 회귀 모델

# 회귀 모델
# 서울시 전체 지역
fit_all <- lm(all$all_py~ all$month)
# 선택 지역
fit_sel <- lm(sel$sel_py~ sel$month)
# 결과 확인
summary(fit_all)
summary(fit_sel)
# 회귀계수 = 기울기
coef_all <- summary(fit_all)$coefficients[2]
coef_sel <- summary(fit_sel)$coefficients[2]
# 1년의 변화량
coef_all <- round(coef_all,1)*365
coef_sel <- round(coef_sel,1)*365
coef_all;coef_sel

8) 회귀선 그리기

# 회귀선 그리기
library(ggplot2)
sel_p <- ggplot(sel, aes(x = month, y = sel_py))+
  geom_line(color = "red", size = 1) +
  xlab("Month")+
  ylab("Price")+
  stat_smooth(method = "lm",
              color = "gray",
              linetype = "dashed" ) +
  theme_bw()
# 서울시 전체 지역
sel_p + geom_line(data = all, aes(x = month, y =all_py), color="blue", size = 1)
head(all)

9) 주석 추가

# 서울시 선택 지역 주석 추가
# hjust(왼쪽, 오른쪽 0~1에 따라)
# vjust(위, 아래 0~1에 따라)
sel_grob <- grobTree(textGrob(paste0("Selected:", coef_sel),
                  x = 0.1,
                  y = 0.9,
                  hjust = 0,
                  gp = gpar(col = "red",
                            fontsize = 14,
                            fontface = "bold")))



# 서울시 전체 지역 주석 추가
all_grob <- grobTree(textGrob(paste0("All:", coef_all),
                              x = 0.1,
                              y = 0.85,
                              hjust = 0,
                              gp = gpar(col = "blue",
                                        fontsize = 14,
                                        fontface = "italic")))

# 주석 추가하여 다시 시각화
sel_p + geom_line(data = all, aes(x = month, y =all_py), color="blue", size = 1)+
  annotation_custom(sel_grob)+
  annotation_custom(all_grob)

 

3. 통계 분석과 시각화 : 주성분 분석하기 CP 8-4

1) 이 동네 단지별 특징은 무엇일까? : 주성분 분석

# 주성분 분석 PCA (Principal Component Analysis)
# 데이터 불러오기
# 선택 지역
load("./data/sel.rdata")
head(sel)
# 주성분 분석에 필요한 데이터 만들기
unique(sel$apt_nm)
# 아파트 별 평균값
pca_data <- aggregate(list(sel$con_year, sel$floor, sel$py, sel$area), by = list(sel$apt_nm),mean)
# 변수 이름 변경
colnames(pca_data) <- c("apt_nm","con_year","floor","py","area")
head(pca_data)
# 주성분 분석
pca <- prcomp(~ con_year + floor + py +area,
        data = pca_data,
        scale = T) # 표준화 = z점수 = 변동성 맞춰주는 작업
summary(pca)

2) 최적의 주성분 개수 결정 후 시각화

# 최적의 주성분 개수 결정
# 표준편차
# 분산 비율
# 분산 누적 비율 : 80% 이상이면 충분함, 연구자가 주관적 판단
# 다른 방법 : 분산이 1보다 큰 주성분
pca$sdev^2
which(pca$sdev^2 > 1)
max(which(pca$sdev^2 > 1))
# 관대하게 보는 경우에는 0.7보다 큰 경우도 사용함
pca$sdev^2
which(pca$sdev^2 > 0.7)
max(which(pca$sdev^2 > 0.7))

# => 주성분 2개 선택

# 시각화
# biplot : 주성분 분석 결과 중에서 가장 중요한 두 개의 축으로 시각화 방법
# 화살표 방향 & 길이
# ggplot2의 확장판 사용 시각화
autoplot(pca)
autoplot(pca,
         loadings.label = T,
         loadings.label.size = 5) 
# 아파트 이름 추가
autoplot(pca,
         loadings.label = T,
         loadings.label.size = 5) +
  geom_label(aes(label=pca_data$apt_nm),
             size=5)

 

autoplot(pca, loadings.label = T, loadings.label.size = 5) + geom_label(aes(label=pca_data$apt_nm), size=5)

 

 

 

* 새로 배운 함수 (핵심)

추가된 plot 의 종류 (autoplot)

aggregate

annotation_custom(sel_grob)

grobTree, textGrob

stat_smooth

addCircleMarkers

unlist

addLayersControl

addRasterImage

                                                                                            

 

728x90
반응형
LIST