# Name 컬럼을 인덱스로 설정
# pd.pivot_table(df, index="Name")
df.pivot_table(index="Name")
# 멀티 인덱스 설정
df.pivot_table(index=["Name", "Rep", "Manager"])
# value 설정
df.pivot_table(index=["Manager", "Rep"], values="Price")
# Price 컬럼 sum 연산 적용 (aggfunc)
df.pivot_table(index=["Manager", "Rep"], values="Price", aggfunc=np.sum)
# Product를 컬럼으로 지정
df.pivot_table(index=["Manager", "Rep"], values="Price", columns="Product", aggfunc=np.sum)
# Nan 값 설정 : fill_value
df.pivot_table(index=["Manager", "Rep"], values="Price", columns="Product", aggfunc=np.sum, fill_value=0)
crime_station = crime_raw_data.pivot_table(
crime_raw_data,
index="구분",
columns=["죄종", "발생검거"],
aggfunc=[np.sum])
crime_station.head()
crime_station.columns = crime_station.columns.droplevel([0, 1]) # 다중 컬럼에서 특정 컬럼 제거
crime_station.columns
count = 0
for idx, rows in crime_station.iterrows():
station_name = "서울" + str(idx) + "경찰서"
tmp = gmaps.geocode(station_name, language="ko")
tmp[0].get("formatted_address")
tmp_gu = tmp[0].get("formatted_address")
lat = tmp[0].get("geometry")["location"]["lat"]
lng = tmp[0].get("geometry")["location"]["lng"]
crime_station.loc[idx, "lat"] = lat
crime_station.loc[idx, "lng"] = lng
crime_station.loc[idx, "구별"] = tmp_gu.split()[2]
print(count)
count = count + 1
tmp = [
crime_station.columns.get_level_values(0)[n] + crime_station.columns.get_level_values(1)[n]
for n in range(0, len(crime_station.columns.get_level_values(0)))
]
crime_station.columns = tmp
crime_anal_gu = pd.pivot_table(crime_anal_station, index="구별", aggfunc=np.sum)
del crime_anal_gu["lat"]
crime_anal_gu.drop("lng", axis=1, inplace=True)
crime_anal_gu.head()
target = ["강간검거율", "강도검거율", "살인검거율", "절도검거율", "폭력검거율"]
num = ["강간검거", "강도검거", "살인검거", "절도검거", "폭력검거"]
den = ["강간발생", "강도발생", "살인발생", "절도발생", "폭력발생"]
crime_anal_gu[target] = crime_anal_gu[num].div(crime_anal_gu[den].values) * 100
crime_anal_gu.head()
# 필요 없는 컬럼 제거
del crime_anal_gu["강간검거"]
del crime_anal_gu["강도검거"]
crime_anal_gu.drop(["살인검거", "절도검거", "폭력검거"], axis=1, inplace=True)
crime_anal_gu.head()
# 100보다 큰 숫자 찾아서 바꾸기
crime_anal_gu[crime_anal_gu[target] > 100] = 100
crime_anal_gu.head()
col = ["살인", "강도", "강간", "절도", "폭력"]
crime_anal_norm = crime_anal_gu[col] / crime_anal_gu[col].max()
crime_anal_norm.head()
# 검거율 추가
col2 = ["강간검거율", "강도검거율", "살인검거율", "절도검거율", "폭력검거율"]
crime_anal_norm[col2] = crime_anal_gu[col2]
crime_anal_norm.head()
# 정규화된 범죄발생 건수 전체의 평균을 구해서 범죄 컬럼 대표값으로 사용
col = ["강간", "강도", "살인", "절도", "폭력"]
crime_anal_norm["범죄"] = np.mean(crime_anal_norm[col], axis=1)
crime_anal_norm.head()
# 검거율의 평균을 구해서 검거 컬럼의 대표값으로 사용
col = ["강간검거율", "강도검거율", "살인검거율", "절도검거율", "폭력검거율"]
crime_anal_norm["검거"] = np.mean(crime_anal_norm[col], axis=1) # axis=1 행을 따라서 연산하는 옵션
crime_anal_norm.head()
import matplotlib.pyplot as plt
import seaborn as sns
# pairplot 강도, 살인, 폭력에 대한 상관관계 확인
# 해석1. 폭력 사건이 살인으로 이어지는 경우가 강도 사건이 살인으로 이어지는 것 보다 더 많다.
# 해석2. 강도와 폭력은 상관관계가 매우 높다.
sns.pairplot(data=crime_anal_norm, vars=["살인", "강도", "폭력"], kind="reg", height=3);
# "인구수", "CCTV"와 "살인", "강도"의 상관관계 확인
# 해석1-1. 인구수가 증가하는 것에 비해 강도가 많이 증가한다고 볼 수는 없다. (아웃라이어도 존재하며, 이를 제외하면 증가폭은 더욱 줄어들 것이다)
# 해석1-2. 강남3구가 인구수가 많은 곳이라면, 강도 발생 비율이 낮으니까 안전하다고 느낄 수 있지 않을까?
# 해석2-1. 인구수가 증가함에 따라 살인은 증가하는 경향을 보인다.
# 해석2-2. CCTV가 많이 설치되어있을 수록 강도 사건이 많이 일어난다? 이는 해석의 오류. 그렇다면 CCTV가 많아서 강도사건이 많이 발생하니까, CCTV를 줄여야한다 라고 연결될 수 있다.
# 해석2-2. 강도 사건이 많이 발생하는 곳에 CCTV를 많이 설치한 것일 수도 있다.
# 해석2-2. 아웃라이어를 제외하면, 회귀선이 조금 더 내려가서 해석을 달리 할 수 있는 여지가 있다.
def drawGraph():
sns.pairplot(
data=crime_anal_norm,
x_vars=["인구수", "CCTV"],
y_vars=["살인", "강도"],
kind="reg",
height=4
)
plt.show()
drawGraph()
# "인구수", "CCTV"와 "살인검거율", "폭력검거율"의 상관관계 확인
# 해석1-1. 인구수가 증가할 수록 폭력검거율이 떨어진다.
# 해석2-1. 인구수와 살인검거율은 조금 높아지는 것 같은 느낌?
# 해석3-1. CCTV와 살인검거율은 해석하기 애매(100에 모여있는 이유는, 검거율은 100으로 제한했기 때문)
# 해석4-1. CCTV가 증가할수록 폭력검거율이 약간 하향세를 보인다.
def drawGraph():
sns.pairplot(
data=crime_anal_norm,
x_vars=["인구수", "CCTV"],
y_vars=["살인검거율", "폭력검거율"],
kind="reg",
height=4
)
plt.show()
drawGraph()
# "인구수", "CCTV"와 "절도검거율", "강도검거율"의 상관관계 확인
# 해석1-1. CCTV가 증가할수록 절도검거율이 감소하고 있다.
# 해석2-1. CCTV가 증가할수록 강도검거율은 증가하고 있다.
def drawGraph():
sns.pairplot(
data=crime_anal_norm,
x_vars=["인구수", "CCTV"],
y_vars=["절도검거율", "강도검거율"],
kind="reg",
height=4
)
plt.show()
drawGraph()
# 검거율 heatmap
# "검거" 컬럼을 기준으로 정렬
def drawGraph():
# 데이터 프레임 생성
target_col = ["강간검거율", "강도검거율", "살인검거율", "절도검거율", "폭력검거율", "검거"]
crime_anal_norm_sort = crime_anal_norm.sort_values(by="검거", ascending=False) # 내림차순
# 그래프 설정
plt.figure(figsize=(10, 10))
sns.heatmap(
data=crime_anal_norm_sort[target_col],
annot=True, # 데이터값 표현
fmt="f", # d: 정수, f: 실수
linewidths=0.5, # 간격설정
cmap="RdPu",
)
plt.title("범죄 검거 비율(정규화된 검거의 합으로 정렬")
plt.show()
# 범죄발생 건수 heatmap
# "범죄" 컬럼을 기준으로 정렬
def drawGraph():
# 데이터 프레임 생성
target_col = ["살인", "강도", "강간", "절도", "폭력", "범죄"]
crime_anal_norm_sort = crime_anal_norm.sort_values(by="범죄", ascending=False) # 내림차순
# 그래프 설정
plt.figure(figsize=(10, 10))
sns.heatmap(
data=crime_anal_norm_sort[target_col],
annot=True, # 데이터값 표현
fmt="f", # 실수값으로 표현
linewidths=0.5, # 간격설정
cmap="RdPu",
)
plt.title("범죄 비율(정규화된 발생 건수로 정렬)")
plt.show()
# 강남구는 살인을 제외하면, 전부 1등
# 서초구도 상위권에 속함
# 검거율은 낮은데, 범죄 발생 비율이 높다.
# 강남 송파 서초구가 과연 안전할까? 라는 의문을 계속 가질 수 있음
drawGraph()
#5대 범죄 발생 건수 지도 시각화
my_map = folium.Map(
location=[37.5502, 126.982],
zoom_start=11,
tiles='Stamen toner')
folium.Choropleth(
geo_data=geo_str,
data=crime_anal_norm['범죄'],
columns=[crime_anal_norm.index, crime_anal_norm['범죄']],
key_on='feature.id',
fill_color='PuRd',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='정규화된 5대 범죄 발생 건수'
).add_to(my_map)
my_map
#인구 대비 범죄 발생 건수 지도 시각화
tmp_criminal = crime_anal_norm['범죄'] / crime_anal_norm['인구수']
my_map = folium.Map(
location=[37.5502, 126.982],
zoom_start=11,
tiles='Stamen toner')
folium.Choropleth(
geo_data=geo_str,
data=tmp_criminal,
columns=[crime_anal_norm.index, tmp_criminal],
key_on='feature.id',
fill_color='PuRd',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='인구 대비 범죄 발생 건수'
).add_to(my_map)
my_map
#경찰서 위치 마커 표시
my_map = folium.Map(
location=[37.5502, 126.982], zoom_start=11)
for idx, rows in crime_anal_station.iterrows():
folium.Marker(
location=[rows['lat'],rows['lng']]
).add_to(my_map)
my_map
#검거에 값을 곱한 뒤 원에 넓이 적용
my_map = folium.Map(
location=[37.5502, 126.982], zoom_start=11)
folium.Choropleth(
geo_data=geo_str,
data=crime_anal_norm['범죄'],
columns=[crime_anal_norm.index, crime_anal_norm['범죄']],
key_on='feature.id',
fill_color='PuRd',
fill_opacity=0.7,
line_opacity=0.2,
).add_to(my_map)
for idx, rows in crime_anal_station.iterrows():
folium.CircleMarker(
location=[rows['lat'],rows['lng']],
radius=rows['검거']*50,
popup=rows['구분']+' : '+ '%.2f'%rows['검거'],
color='#3186cc',
fill=True,
fill_color='#3186cc'
).add_to(my_map)
my_map
col = ['살인','강도','강간','절도','폭력']
crime_loc_norm = crime_loc / crime_loc.max()
crime_loc.head()
crime_loc_norm['종합'] = np.mean(crime_loc_norm, axis=1)
crime_loc_norm_sort = crime_loc_norm.sort_values('종합',ascending=False)
def drawGraph():
plt.figure(figsize=(10,10))
sns.heatmap(
crime_loc_norm_sort,
annot=True,
fmt='f',
linewidths=0.5,
cmap='RdPu')
plt.title("범죄 발생 장소")
plt.show()
drawGraph()
조금 더 복잡한 데이터를 정리해주는 마법의 pivot_table(). 이를 잘 사용하려면 내가 뭘 보고 있는지, 뭘 하려는지 알아야 한다는 것이다. 데이터 정리를 잘 해야 뭐가 보인다.