-
파이썬으로 시작하는 데이터 사이언스 - 4. 데이터 전처리공부일기/부스트코스 2020. 11. 24. 19:02
앞서 사용한 csv파일을 그대로 사용해 서울에 위치한 종합병원만을 찾아보자.
- 텍스트 데이터 색인하기
.str.contains()
df_seoul_hospital.loc[~df_seoul_hospital["상호명"].str.contains("종합병원"), "상호명"].unique()
.str.contains()를 사용하게 되면 해당 컬럼에서 ()안에 들어있는 문자가 포함됐는지를 boolean 타입으로 출력한다.
~df_seoul_hospital["상호명"].str.contains("종합병원") 을 하게되면 ()안의 문자가 포함 안 된 인덱스를 나타낸다.
.loc을 사용해 "상호명"에 종합병원이 포함된 인덱스들을 필터링하고, "상호명" 컬럼만 가져와 unique()로 어떤 값들이 있는지 list로 표현한다.
위의 코드를 실행한 모습.
이름에 꽃배달, 의료기, 장례식장 등 종합병원이 아닌 것으로 보이는 값들을 drop_row라는 변수로 지정하고 tolist()함수를 이용해 리스트 형태로 만든다.
drop_row = df_seoul_hospital[df_seoul_hospital["상호명"].str.contains("꽃배달|의료기|장례식장|상담소|어린이집")].index drop_row = drop_row.tolist() drop_row
코드를 실행하면
[1917, 2803, 4431, 4644, 7938, 10283, 47008, 60645, 70177]
의 값을 출력한다. 현재 drop_row에는 contains()의 괄호 부분 안에 있는 문자열들을 포함하는 값들의 인덱스를 리스트형태로 저장하고 있다.
마찬가지로 "상호명"이 의원으로 끝나는 업체를 필터링하는 코드를 작성한 후 drop_row2 변수에 담아준다.
drop_row2 = df_seoul_hospital[df_seoul_hospital["상호명"].str.endswith("의원")].index drop_row2 = drop_row2.tolist() drop_row2
실행해보면 [8479, 12854, 13715, 14966, 16091, 18047, 20200, 20415, 30706, 32889, 34459, 34720, 35696, 37251, 45120, 49626, 51575, 55133, 56320, 56404, 56688, 57551, 62113, 76508] 가 출력된다.
두 변수를 더하면 "상호명"에 꽃배달, 의료기, 장례식장, 상담소, 어린이집, 의원이 포함된 값들의 인덱스를 리스트형태로 지니게 되고, 이를 다시 drop_row에 대입하고, 서울 종합병원의 데이터프레임에서 제거한다.
drop_row = drop_row + drop_row2 print(df_seoul_hospital.shape) df_seoul_hospital = df_seoul_hospital.drop(drop_row, axis=0) print(df_seoul_hospital.shape)
위의 코드를 실행하면
(91, 29)
(58, 29)
가 출력되고, 이는 "서울특별시"에 있는 "상권업종분류명"이 종합병원인 값들에서 꽃배달, 의료기, 장례식장, 상담소, 어린이집, 의원을 상호명에 지니고 있는 값들을 제거한 데이터가 58개로 전처리되었음을 보여준다.
시각화해서 표현하면
plt.figure(figsize=(15,4)) sns.countplot(data=df_seoul_hospital, x="시군구명", order=df_seoul_hospital["시군구명"].value_counts().index)
x축의 값들이 많기 때문에 글자가 겹치는 걸 방지하기 위해, figsize를 지정해주고, x축 값을 지정하고 내림차순 정렬을 위해 order 속성을 사용해주면 아래와 같은 실행결과를 얻을 수 있다.
다시 df_seoul_hospital["상호명"].unique() 를 입력해 상호명 리스트를 살펴보면, 연구소, 인공신장실, 마취과 등등 종합병원이 아닌 것으로 보이는 값들이 아직 남아있긴 하다.
- 특정 지역만 보기
"시도명"을 필터링 하는 작업으로 각 시도별 의료기관 데이터를 얻을 수 있다. 얻어진 데이터를 지도에 표기하거나, 시각적으로 표현하고 싶다면? scatter plot를 사용하거나, Folium을 사용해 지도 위에 체크포인트를 만들 수도 있다.
scatter()
df_seoul = df[df["시도명"] == "서울특별시"].copy() # df_seoul에 "시도명"이 서울특별시에 해당하는 데이터프레임을 만들어 복사한다. # copy()를 사용해 df_seoul의 데이터가 변해도 원본 데이터는 유지될 수 있도록 한다. # 1 df_seoul["시군구명"].value_counts().plot.bar(figsize=(10,4), rot=30) # 판다스의 기본 막대그래프를 이용해 서울에 있는 의료기관을 각 구별로 나눈 모습을 확인. # 2 df_seoul[["경도", "위도", "시군구명"]].plot.scatter(x="경도", y="위도", figsize=(8,7), grid=True) # scatter를 사용해 경도와 위도를 각 x축, y축 에 대입해 지도형태로 나타낸다.
scatter plot을 사용해 위도와 경도 값을 입력해보니 서울지도 모양의 그래프가 나타났다. 가운데는 한강. 중간에 구멍난 부분들은 산이 있는 곳일 것이다.
마찬가지로 seaborn의 scatter plot을 이용할 수도 있다.
# 1 plt.figure(figsize=(15,4)) sns.countplot(data=df_seoul, x="시군구명") # 서울특별시의 구별 의료기관 분포를 막대그래프 형태로 나타낸다. # 2 sns.scatterplot(data=df_seoul, x="경도", y="위도", hue="시군구명") # 구별 의료기관 분포를 나타낸 그래프, 경도와 위도 값을 각각 x,y 축으로 잡고 hue를 통해 색상 구별을 줬다.
seaborn을 활용하는 경우 hue 값을 정해줌으로써 색상을 달리해 시각적으로 더 직관적인 구별을 할 수 있게 해준다. 물론 위의 그래프 같은 경우 중구와 도봉구, 은평구와 강북구 등은 색이 너무 비슷해 지리를 모르는 경우 찾기가 쉽지 않을 것 같다.. 어떤 정보의 암묵적인 동의가 없다면 파이그래프처럼 값이 많으면 더 구별하기 힘들수도 있겠구나
plt.figure(figsize=(9, 8)) sns.scatterplot(data=df_seoul, x="경도", y="위도", hue="상권업종중분류명")
이것은 같은 데이터를 "상권업종중분류명"에 따라 구별한 것이다.
파란색 병원이 압도적으로 많이 분포돼 있고, 주황색, 빨간색 순으로 분포돼 있는 듯하다.
다음으로 전국에 있는 의료기관을 "시도명"으로 나눠보자.
plt.figure(figsize=(9, 8)) sns.scatterplot(data=df, x="경도", y="위도", hue="시도명")
실행하면 대한민국의 지도가 나타난다 !
울릉도에는 의료기관이 하나 있는 듯하고, 제주도의 경우 한라산때문에 가장자리에 의료기관들이 분포해 있는 것 같다.
동쪽을 보면 태백산맥이 위치한 부분들을 피해 의료기관들이 분포해 있는 모습도 확인할 수 있다.
지금까지는 위도와 경도 값으로 그래프를 지도형태로만 확인했지만 실제 지도에 데이터의 값을 입력하려면?
Folium을 사용하면 된다.
- Folium으로 지도 활용하기
folium.Map(location = ?, zoom_start = ?)
import folium folium.Map()
folium을 import하고 실행하면 세계지도가 나타난다.
서울의 종합병원 값을 지도에 표시해보고 싶다면 서울의 위도 평균값과 경도 평균값을 location 값으로 주면 된다.
x = df_seoul_hospital["경도"].mean() y = df_seoul_hospital["위도"].mean() # x, y에 각각 서울 종합병원 "경도", "위도" 값의 평균을 대입한다. map = folium.Map(location=[df_seoul_hospital["위도"].mean(), df_seoul_hospital["경도"].mean()], zoom_start=12) map
location은 위도와 경도 값을 입력해주면 되고, zoom_start는 얼만큼 확대해서 보여줄 것인지를 입력해주면 된다.
map에 위의 확대된 지도를 대입해주고, for 문을 이용해 "상호명"과 "도로명주소"를 보여주는 마커를 생성해보자.
folium.Marker()
for n in df_seoul_hospital.index: name = df_seoul_hospital.loc[n, "상호명"] address = df_seoul_hospital.loc[n, "도로명주소"] popup = f"{name}-{address}" location = [df_seoul_hospital.loc[n, "위도"], df_seoul_hospital.loc[n, "경도"]] folium.Marker( location = location, popup = popup, ).add_to(map) # map.save("index.html") # folium 자체에서 글자가 깨지는 현상이 발생해 html형식으로 저장하고 따로 확인했다. 반드시 저장할 필요는 없음. map
.Marker()의 ()안에 location, popup을 이용해서 마커를 찍을 위치, 마커를 클릭했을 때 팝업에 나오는 정보를 입력할 수 있다.
가설을 세우고, 원하는 데이터를 얻기 위해 데이터를 색인하고 전처리하는 작업은 많은 시간을 필요로 한다.
제대로 전처리 되지 않은 데이터는 낮은 신뢰도를 지니게 될 것이고, 이는 데이터를 분석하는데 의미가 없지 않을까.
데이터를 필터링할 수 있는 코드를 아는 것도 중요하지만 어떤 데이터를 어떻게 처리할지가 더 중요하게 배워야 할 점인 것 같다. 아직 어떤 가설을 세우면 좋을지 많이 고민하고 연습해야하면 좋을까 싶었는데, 예시로 주제를 던져준 부분이 있어 다음엔 해당 주제들을 분석하고 배운 내용을 정리해야겠다!
'공부일기 > 부스트코스' 카테고리의 다른 글
웹 백엔드 - 1. SQL & JDBC 프로그래밍(2) (0) 2021.01.02 웹 백엔드 - 1. SQL & JDBC 프로그래밍(1) (0) 2021.01.01 파이썬으로 시작하는 데이터 사이언스 - 3. 데이터 요약 및 추출 (0) 2020.11.20 파이썬으로 시작하는 데이터 사이언스 - 2. 공공데이터 로드 및 데이터 미리보기 (0) 2020.11.19 파이썬으로 시작하는 데이터 사이언스 - 1. Pandas (0) 2020.11.18