웹 크롤링/파이썬 프로그래밍-1(서울시 CCTV)

한영석·2022년 8월 18일
0

Pandas에서 데이터를 병합하는 방법

  • pd.concat()

  • pd.merge()

  • pd.join()

  • pd.merge(left, right)

# 딕셔너리 안의 리스트 형태 

left = pd.DataFrame({
    "key": ["K0", "K4", "K2", "K3"],
    "A": ["A0", "A1", "A2", "A3"],
    "B": ["B0", "B1","B2", "B3"]
})
left 

# 리스트 안의 딕셔너리 형태 

right = pd.DataFrame([
    {"key":"K0", "C":"C0", "D":"D0"},
    {"key":"K1", "C":"C1", "D":"D1"},
    {"key":"K2", "C":"C2", "D":"D2"},
    {"key":"K3", "C":"C3", "D":"D3"},
])
right


  • pd.merge()
    • 두 데이터 프레임에서 컬럼이나 인덱스를 기준으로 잡고 병합하는 방법
    • 기준이 되는 컬럼이나 인덱스를 키값이라고 합니다
    • 기준이 되는 키값은 두 데이터 프레임에 모두 포함되어 있어야 합니다
pd.merge(left, right, how="inner", on="key")

pd.merge(left, right, how="left", on="key")

pd.merge(left, right, how="right", on="key")

pd.merge(left, right, how="outer", on="key")

  • 년도별 데이터 컬럼 삭제
    • del
    • drop()
del data_result["2013년도 이전"]
del data_result["2014년"]
data_result.head(3)

data_result.drop(["2015년", "2016년"], axis=1, inplace=True)
data_result.head()

  • 인덱스 변경
    • set_index()
    • 선택한 컬럼을 데이터 프레임의 인덱스로 지정
data_result.set_index("구별", inplace=True)
data_result.head()

  • 상관계수
    • corr()
    • correlation 의 약자입니다
    • 상관계수가 0.2 이상인 데이터를 비교
data_result.corr()

data_result.info()

data_result["CCTV비율"] = data_result["소계"] / data_result["인구수"] 
data_result["CCTV비율"] = data_result["CCTV비율"] * 100 
data_result.head()

data_result.sort_values(by="CCTV비율", ascending=False).head()

data_result.sort_values(by="CCTV비율", ascending=True).head()

matplotlib 기초

  • matplotlib 그래프 기본 형태

    • plt.figure(figsize=(10, 6))
    • plt.plot(x, y)
    • plt.show
plt.figure(figsize=(10, 6))
plt.plot([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 1, 2, 3, 4, 2, 3, 5, -1, 3])
plt.show()

  • 삼각함수 그리기
    • np.arange(a, b, s): a부터 b까지 s의 간격
    • np.sin(value)
import numpy as np  # numpy를 사용하기위한 불러오기

t = np.arange(0, 12, 0.01)
y = np.sin(t)

plt.figure(figsize=(10, 6)) # figsize=(가로, 세로)
plt.plot(t, np.sin(t))
plt.plot(t, np.cos(t))
plt.show() # 그래프로 출력하여 보여주는 코드

  • 옵션 추가(커스터마이징)
    • 격자무늬 추가
    • 그래프 제목 추가
    • x축, y축 제목 추가
    • 주황색, 파란색 선 데이터 의미 구분
def drawGraph():

    plt.figure(figsize=(10, 6))
    plt.plot(t, np.sin(t), label="sin")
    plt.plot(t, np.cos(t), label="cos")
    plt.grid(True) # 격자무늬 추가
    plt.legend(loc=2) # 범례 (선 데이터 의미 구분) / loc로 범례의 위치 지정 가능
    plt.title("Example of sinewave") # 그래프 제목
    plt.xlabel("time") # x축 제목
    plt.ylabel("Amplitude") # 진폭(y축 제목) 
    plt.show()
drawGraph()

  • 여러가지 그래프 커스텀
t = np.arange(0, 5, 0.5)
plt.figure(figsize=(10, 6))
plt.plot(t, t, "r--") # red ---- 
plt.plot(t, t ** 2, "bs")
plt.plot(t, t ** 3, "g>")
plt.show()

# t = [0, 1, 2, 3, 4, 5, 6]
t = list(range(0, 7))
y = [1, 4, 5, 8, 9, 5, 3]
def drawGraph():

    plt.figure(figsize=(10, 6))
    plt.plot(
        t,
        y,
        color="red", 
        linestyle="--", 
        marker="o", 
        markerfacecolor="blue",
        markersize=10, 
    )

    plt.xlim([-0.5, 6.5]) 
    plt.ylim([0.5, 9.5])
    plt.show() 
    
drawGraph()

  • scatter plot
t = np.array(range(0, 10))
y = np.array([9, 8, 7, 9, 8, 3, 2, 4, 3, 4])
def drawGraph():

    plt.figure(figsize=(10, 6))
    plt.scatter(t, y)
    plt.show()
    
drawGraph()

colormap = t 

def drawGraph():

    plt.figure(figsize=(10, 6))
    plt.scatter(t, y, s=150, c=colormap, marker="<")
    # s(마커 사이즈)
    plt.colorbar()
    plt.show()
    
drawGraph()

  • Pandas에서 plot 그리기
    • matplotlib 을 가져와서 사용합니다
data_result.head()
# 판다스 데이터 불러오기

data_result["인구수"].plot(kind="bar", figsize=(10, 10));

data_result["인구수"].plot(kind="barh", figsize=(10, 10));

데이터 시각화

import matplotlib.pyplot as plt 
# import matplotlib as mpl 
from matplotlib import rc

plt.rcParams["axes.unicode_minus"] = False # 마이너스 부호 때문에 한글이 깨질 수가 있어 주는 설정
rc("font", family="Arial Unicode MS") # Windows: Malgun Gothic 
# %matplotlib inline (쥬피터 노트북의 시각화를 위한 기본설정)
get_ipython().run_line_magic("matplotlib", "inline") (쥬피터 노트북의 시각화를 위한 기본설정)

data_result.head()

  • 소계 컬럼 시각화
data_result["소계"].plot(kind="barh", grid=True, figsize=(10, 10));
# Pandas DataFrame은 데이터 변수에서 바로 plot() 명령을 사용할 수 있다
# 그리고 데이터(컬럼)가 많은 경우 정렬한 후 그리는 것이 효과적일 때가 많다

  • 소계 컬럼 시각화(정렬)
def drawGraph():
    data_result["소계"].sort_values().plot(
        kind="barh", 
        grid=True, 
        title="가장 CCTV가 많은 구", 
        figsize=(10, 10)
        );
drawGraph()

data_result.head()

  • CCTV비율 컬럼 시각화
def drawGraph():
    data_result["CCTV비율"].sort_values().plot(
        kind="barh", grid=True, title="가장 CCTV가 많은 구", figsize=(10, 10));
drawGraph()


데이터의 경향 표시

data_result.head()

  • 인구수와 소계 컬럼으로 scatter plot 그리기(scatter : 산점도)
def drawGraph():
    plt.figure(figsize=(14, 10))
    plt.scatter(data_result["인구수"], data_result["소계"], s=50)
    plt.xlabel("인구수")
    plt.ylabel("CCTV")
    plt.grid(True)
    plt.show() 
drawGraph()

  • Numpy를 이용한 1차 직선 만들기
    • np.polyfit(): 직선을 구성하기 위한 계수를 계산
    • np.poly1d(): polyfit 으로 찾은 계수로 파이썬에서 사용할 수 있는 함수로 만들어주는 기능
import numpy as np 

fp1 = np.polyfit(data_result["인구수"], data_result["소계"], 1)

f1 = np.poly1d(fp1) # polyfit에서 찾은 계수를 넣어서 함수 완성
# 인구 400,000인 구에서 서울시의 전체 경향에 맞는 적당한 CCTV 수를 알고 싶다면?
f1(400000)

  • 인구가 40만인 구에서 서울시의 전체 경향에 맞는 적당한 CCTV 수는?
    • 경향선을 그리기 위한 X 데이터 생성
    • np.linspace(a, b, n): a부터 b까지 n개의 등간격 데이터 생성
fx = np.linspace(100000, 700000, 100) 
# 100000 부터 700000 사이의 100개의 데이터를 생성

def drawGraph():
    plt.figure(figsize=(14, 10))
    plt.scatter(data_result["인구수"], data_result["소계"], s=50)
    plt.plot(fx, f1(fx), ls="dashed", lw=3, color="g")
    plt.xlabel("인구수")
    plt.ylabel("CCTV")
    plt.grid(True)
    plt.show() 
drawGraph()

강조하고 싶은 데이터를 시각화해보자

  • 그래프 다듬기

  • 경향과의 오차 만들기

    • 경향(trend)과의 오차를 만들자
    • 경향은 f1 함수에 해당 인구를 입력
    • f1(data_result["인구수"])
fp1 = np.polyfit(data_result["인구수"], data_result["소계"], 1)
# np.polyfit(x 데이터, y 데이터, 1 : 1차원 배열)
f1 = np.poly1d(fp1) 
fx = np.linspace(100000, 700000, 100) 
data_result.head(3) # 앞 3개의 데이터 출력

  • 오차 만들기
data_result["오차"] = data_result["소계"] - f1(data_result["인구수"])
data_result.head(1)

# 경향과 비교해서 데이터의 오차가 너무 나는 데이터를 계산 

df_sort_f = data_result.sort_values(by="오차", ascending=False) # 내림차순 
df_sort_t = data_result.sort_values(by="오차", ascending=True) # 오름차순   

# 경향 대비 CCTV를 많이 가진 구 
df_sort_f.head()

# 경향 대비 CCTV를 적게 가진 구 
df_sort_t.head()

from matplotlib.colors import ListedColormap

# color map 을 사용자 정의(user define)로 세팅 
# 색상을 지정해주기위한 설정
color_step = ["#e74c3c", "#2ecc71", "#95a9a6", "#2ecc71", "#3498db", "#3498db"]
my_cmap = ListedColormap(color_step)
def drawGraph():
    
    plt.figure(figsize=(14, 10))
    plt.scatter(data_result["인구수"], data_result["소계"], s=50, c=data_result["오차"], cmap=my_cmap)
    # s : 마커의 크기 ,c : color 세팅에 방금 계산한 경향과의 오차를 적용 ,cmap : 사용자 정의한 맵을 적용
    plt.plot(fx, f1(fx), ls="dashed", lw=3, color="g")

    for n in range(5):
    # 오차가 큰 데이터 아래 위로 5개씩만 큭별히 마커옆에 구 이름을 명시하기 위한 반복문
        # 상위 5개 
        plt.text(
            df_sort_f["인구수"][n] * 1.02, # x 좌표
            df_sort_f["소계"][n] * 0.98,  # y 좌표
            df_sort_f.index[n], # title 
            fontsize=15,
        )
    
        # 하위 5개 
        plt.text(
            df_sort_t["인구수"][n] * 1.02, 
            df_sort_t["소계"][n] * 0.98,
            df_sort_t.index[n],
            fontsize=15
        )
        
    
    plt.xlabel("인구수")
    plt.ylabel("CCTV")
    plt.colorbar()
    plt.grid(True)
    plt.show() 
drawGraph()

  • 완성된 데이터 저장하기
# CSV파일로 데이터 저장
data_result.to_csv("../data/01. CCTV_result.csv", sep=",", encoding="utf-8")
profile
코딩공부중

0개의 댓글