<reponame>rosa-yuri/BigCampus_project
### k-means & 접근성 분석 ###
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from scipy.spatial.distance import cdist, pdist

np.random.seed(777)

## 어린이집 데이터 전처리 ##
all_center = pd.read_csv("d:/project_data/test/all_test_1.csv", sep=",", encoding="euc-kr")
x_test = all_center[all_center['Type'] == "국공립"] # 국공립만 선택
X = x_test.iloc[:-15, 15:17]
X_test = x_test.iloc[:, 15:17]


## train_test split ## --> train: x_test / predict: x_test (cluster)

## k-means ##
# 최적 클러스터 k 찾기 # -> elbow graph
K = 150

def k_search():
    ## 최적의 k를 엘보 그래프로 찾는 함수 ##
    global K
    KM = [KMeans(n_clusters=k).fit(X) for k in K] # 각각의 k(25~300까지 5단위), k-means 명령어
    ss = [silhouette_score(X, k.labels_, metric='euclidean') for k in KM]
    centroids = [k.cluster_centers_ for k in KM] # 각 k-means마다 클러스터별 center 거리
    D_k = [cdist(X, centrds, 'euclidean') for centrds in centroids] # 센터와 X데이터간의 거리
    cIdx = [np.argmin(D, axis=1) for D in D_k] # 최소 거리
    dist = [np.min(D, axis=1) for D in D_k] # 최소 거리
    avgWithinSS = [sum(d) / X.shape[0] for d in dist] # 클러스터 내 제곱 평균 (sum of sq)
    wcss = [sum(d**2) for d in dist] # sq 계산
    tss = sum(pdist(X)**2 / X.shape[0]) # X각각의 거리 제곱 / m --> 평균
    bss = tss - wcss
    ## 엘보 곡선 ## ----> 시각화 하세요~!
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(K, avgWithinSS, 'b*-')
    plt.grid(True)
    plt.xlabel("# of clusters")
    plt.ylabel("Avg of SS")
    ## 분산 ## ----> 이것도 ~!
    fig2 = plt.figure()
    ax = fig2.add_subplot(111)
    ax.plot(K, bss/tss*100, 'b*-')
    plt.grid(True)
    plt.xlabel("# of cluster")
    plt.ylabel("var")
    plt.show()
    return ss

#ss = k_search() # k -- > 구별 25 / 100로 진행

# n_cluster = 150, max_iter=3000 #
k_means = KMeans(n_clusters=K, max_iter=3000, random_state=77)
k_means.fit(X)
k_cluster = k_means.predict(X_test)
x_test['k_cluster'] = k_cluster

ss = silhouette_score(X, k_means.labels_, metric='euclidean')
#print(ss) # 0.40


# 한글 폰트 깨지는 문제 #
from matplotlib import font_manager, rc
font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)

# 시각화 그래프 # --> 구별 평균 추정값 (TEST) // 그냥 거리만 나타낸 시각화
#fig = plt.figure()
#for i in range(K):
#    scat = plt.scatter(x_test[x_test['k_cluster']==i].iloc[:, 14], x_test[x_test['k_cluster']==i].iloc[:, 15],
#                       s=10)
#    
#
#fig.show()

### 
### 센터 접근성 분석 ###
### k-means 클러스터를 이용해, 예측한 인구에 따른 '센터'의 접근성 분석 ###
center = k_means.cluster_centers_ # 200개의 클러스터
center = pd.DataFrame(center)
groupby = x_test.sort_values(['k_cluster'])

def distance(a, b):
    ## 좌표계 사이의 거리를 km 계산으로 ##
    lon1, lat1 = a[0], a[1]
    lon2, lat2 = float("%.6f" %b[0]), float("%.6f" %b[1])
    R = 6378.137 #// radius of the earth in km
    dlat = (lat2 - lat1) * (np.pi / 180)
    dlon = (lon2 - lon1) * (np.pi / 180)
    a = np.sin((dlat/2))**2 + np.cos(lat1 * np.pi / 180) * np.cos(lat2 * np.pi / 180) * (np.sin(dlon/2))**2
    c = 2 * np.math.atan2(np.sqrt(a), np.sqrt(1-a))
    d = R * c
    return d

def center_access(center_col, pop):
    global k_means, center, K, groupby
#    pop = groupby[['201809']] # (1412, 1)
    groupby[center_col] = 0.01
    xy = np.array(groupby.iloc[:, 15:17])
    center_xy = np.array(center.iloc[:, 0:2])
    tmp = np.zeros_like(groupby[center_col])
    for j in range(len(groupby)):
        if j % 100 == 0: print("center continue..")
        tmpList = []
        for i in range(len(center)):
            gb = groupby[groupby['k_cluster'] == i]
            e = np.int(np.mean(gb[pop]))
            dist = distance(xy[j], center_xy[i])
            tmpList.append(e * (dist*1000) ** -1)
        tmp[j] = np.sum(tmpList)
        groupby[center_col] = tmp
#    groupby['mean'] = groupby['center_access'] / K

def people_access(people_col, center_col):
    global k_means, center, K, groupby
    center[people_col] = 0.01
    xy = np.array(groupby.iloc[:, 15:17])
    center_xy = np.array(center.iloc[:, 0:2])
    tmp = np.zeros_like(center[people_col])
    for j in range(len(center)):
        if j % 100 == 0: print("people continue..")
        tmpList = []
        for i in range(len(groupby)):
            center_acc = groupby[center_col].iloc[i]
            limit = groupby['Max'].iloc[i]
            dist = distance(xy[i], center_xy[j])
            tmpList.append((limit * (dist*1000) ** -1) / (center_acc))
        tmp[j] = np.sum(tmpList)
    center[people_col] = tmp
    for i in range(len(groupby)):
        groupby[people_col].iloc[i] = center[people_col][groupby['k_cluster'].iloc[i]]       
        
center_access('center_access', '201809')
people_access('people_access', 'center_access')
center_access('center_access_2', '202104')
people_access('people_access_2', 'center_access_2')

groupby.to_csv("d:/project_data/test/test_1.csv", encoding="euc-kr", index=0)
#
### k-means & 접근성 분석 ###
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from scipy.spatial.distance import cdist, pdist

np.random.seed(777)

## 어린이집 데이터 전처리 ##
all_center = pd.read_csv("d:/project_data/test/all_test_1.csv", sep=",", encoding="euc-kr")
x_test = all_center[all_center['Type'] == "국공립"] # 국공립만 선택
X = x_test.iloc[:-15, 15:17]
X_test = x_test.iloc[:, 15:17]


## train_test split ## --> train: x_test / predict: x_test (cluster)

## k-means ##
# 최적 클러스터 k 찾기 # -> elbow graph
K = 150

def k_search():
    ## 최적의 k를 엘보 그래프로 찾는 함수 ##
    global K
    KM = [KMeans(n_clusters=k).fit(X) for k in K] # 각각의 k(25~300까지 5단위), k-means 명령어
    ss = [silhouette_score(X, k.labels_, metric='euclidean') for k in KM]
    centroids = [k.cluster_centers_ for k in KM] # 각 k-means마다 클러스터별 center 거리
    D_k = [cdist(X, centrds, 'euclidean') for centrds in centroids] # 센터와 X데이터간의 거리
    cIdx = [np.argmin(D, axis=1) for D in D_k] # 최소 거리
    dist = [np.min(D, axis=1) for D in D_k] # 최소 거리
    avgWithinSS = [sum(d) / X.shape[0] for d in dist] # 클러스터 내 제곱 평균 (sum of sq)
    wcss = [sum(d**2) for d in dist] # sq 계산
    tss = sum(pdist(X)**2 / X.shape[0]) # X각각의 거리 제곱 / m --> 평균
    bss = tss - wcss
    ## 엘보 곡선 ## ----> 시각화 하세요~!
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(K, avgWithinSS, 'b*-')
    plt.grid(True)
    plt.xlabel("# of clusters")
    plt.ylabel("Avg of SS")
    ## 분산 ## ----> 이것도 ~!
    fig2 = plt.figure()
    ax = fig2.add_subplot(111)
    ax.plot(K, bss/tss*100, 'b*-')
    plt.grid(True)
    plt.xlabel("# of cluster")
    plt.ylabel("var")
    plt.show()
    return ss

#ss = k_search() # k -- > 구별 25 / 100로 진행

# n_cluster = 150, max_iter=3000 #
k_means = KMeans(n_clusters=K, max_iter=3000, random_state=77)
k_means.fit(X)
k_cluster = k_means.predict(X_test)
x_test['k_cluster'] = k_cluster

ss = silhouette_score(X, k_means.labels_, metric='euclidean')
#print(ss) # 0.40


# 한글 폰트 깨지는 문제 #
from matplotlib import font_manager, rc
font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)

# 시각화 그래프 # --> 구별 평균 추정값 (TEST) // 그냥 거리만 나타낸 시각화
#fig = plt.figure()
#for i in range(K):
#    scat = plt.scatter(x_test[x_test['k_cluster']==i].iloc[:, 14], x_test[x_test['k_cluster']==i].iloc[:, 15],
#                       s=10)
#    
#
#fig.show()

### 
### 센터 접근성 분석 ###
### k-means 클러스터를 이용해, 예측한 인구에 따른 '센터'의 접근성 분석 ###
center = k_means.cluster_centers_ # 200개의 클러스터
center = pd.DataFrame(center)
groupby = x_test.sort_values(['k_cluster'])

def distance(a, b):
    ## 좌표계 사이의 거리를 km 계산으로 ##
    lon1, lat1 = a[0], a[1]
    lon2, lat2 = float("%.6f" %b[0]), float("%.6f" %b[1])
    R = 6378.137 #// radius of the earth in km
    dlat = (lat2 - lat1) * (np.pi / 180)
    dlon = (lon2 - lon1) * (np.pi / 180)
    a = np.sin((dlat/2))**2 + np.cos(lat1 * np.pi / 180) * np.cos(lat2 * np.pi / 180) * (np.sin(dlon/2))**2
    c = 2 * np.math.atan2(np.sqrt(a), np.sqrt(1-a))
    d = R * c
    return d

def center_access(center_col, pop):
    global k_means, center, K, groupby
#    pop = groupby[['201809']] # (1412, 1)
    groupby[center_col] = 0.01
    xy = np.array(groupby.iloc[:, 15:17])
    center_xy = np.array(center.iloc[:, 0:2])
    tmp = np.zeros_like(groupby[center_col])
    for j in range(len(groupby)):
        if j % 100 == 0: print("center continue..")
        tmpList = []
        for i in range(len(center)):
            gb = groupby[groupby['k_cluster'] == i]
            e = np.int(np.mean(gb[pop]))
            dist = distance(xy[j], center_xy[i])
            tmpList.append(e * (dist*1000) ** -1)
        tmp[j] = np.sum(tmpList)
        groupby[center_col] = tmp
#    groupby['mean'] = groupby['center_access'] / K

def people_access(people_col, center_col):
    global k_means, center, K, groupby
    center[people_col] = 0.01
    xy = np.array(groupby.iloc[:, 15:17])
    center_xy = np.array(center.iloc[:, 0:2])
    tmp = np.zeros_like(center[people_col])
    for j in range(len(center)):
        if j % 100 == 0: print("people continue..")
        tmpList = []
        for i in range(len(groupby)):
            center_acc = groupby[center_col].iloc[i]
            limit = groupby['Max'].iloc[i]
            dist = distance(xy[i], center_xy[j])
            tmpList.append((limit * (dist*1000) ** -1) / (center_acc))
        tmp[j] = np.sum(tmpList)
    center[people_col] = tmp
    for i in range(len(groupby)):
        groupby[people_col].iloc[i] = center[people_col][groupby['k_cluster'].iloc[i]]       
        
center_access('center_access', '201809')
people_access('people_access', 'center_access')
center_access('center_access_2', '202104')
people_access('people_access_2', 'center_access_2')

groupby.to_csv("d:/project_data/test/test_1.csv", encoding="euc-kr", index=0)
#
### k-means & 접근성 분석 ### ## 어린이집 데이터 전처리 ## # 국공립만 선택 ## train_test split ## --> train: x_test / predict: x_test (cluster) ## k-means ## # 최적 클러스터 k 찾기 # -> elbow graph ## 최적의 k를 엘보 그래프로 찾는 함수 ## # 각각의 k(25~300까지 5단위), k-means 명령어 # 각 k-means마다 클러스터별 center 거리 # 센터와 X데이터간의 거리 # 최소 거리 # 최소 거리 # 클러스터 내 제곱 평균 (sum of sq) # sq 계산 # X각각의 거리 제곱 / m --> 평균 ## 엘보 곡선 ## ----> 시각화 하세요~! ## 분산 ## ----> 이것도 ~! #ss = k_search() # k -- > 구별 25 / 100로 진행 # n_cluster = 150, max_iter=3000 # #print(ss) # 0.40 # 한글 폰트 깨지는 문제 # # 시각화 그래프 # --> 구별 평균 추정값 (TEST) // 그냥 거리만 나타낸 시각화 #fig = plt.figure() #for i in range(K): #    scat = plt.scatter(x_test[x_test['k_cluster']==i].iloc[:, 14], x_test[x_test['k_cluster']==i].iloc[:, 15], #                       s=10) # # #fig.show() ### ### 센터 접근성 분석 ### ### k-means 클러스터를 이용해, 예측한 인구에 따른 '센터'의 접근성 분석 ### # 200개의 클러스터 ## 좌표계 사이의 거리를 km 계산으로 ## #// radius of the earth in km #    pop = groupby[['201809']] # (1412, 1) #    groupby['mean'] = groupby['center_access'] / K #