데이터분석/미니프로젝트 02. 웹 데이터 분석(크롤링)

미니프로젝트 02-01-04. 데이터 시각화

책다니엘 2024. 4. 13. 03:50

1. 이제 지금까지 만들어온 데이터를 시각화할 차례다. 우선 데이터를 다시 불러와준다.

import pandas as pd
df = pd.read_csv('../data/03. best_sandwiches_list_chicago_ds_study02.csv')

 

2. 지도 시각화를 위한 라이브러리들을 불러와준다.

import folium
import googlemaps
import numpy as np
from tqdm import tqdm

 

3. 먼저 googlemaps로 주소들을 검색하여 좌표(lat, lng)를 표시해준다.

gmaps_key = 'API키 여기에'
gmaps = googlemaps.Client(key=gmaps_key)

lat = []
lng = []

for idx, row in tqdm(df.iterrows()):
    if not row['Access'] == 'Multiple location':
        target_name = row['Access'] + ', ' + 'Chicago'
        gmaps_output = gmaps.geocode(target_name)
        location_output = gmaps_output[0].get('geometry')
        lat.append(location_output['location']['lat'])
        lng.append(location_output['location']['lng'])
    else:
        lat.append(np.nan)
        lng.append(np.nan)

 

*** 여기서 오류 발생! ***

gmaps_output이 존재하지 않아 아무 값도 들어가지 않는 경우가 생겼다.

해당 경우를 발견할 경우 target_name을 반환하도록 코드를 다시 짰다.

lat = []
lng = []

for idx, row in tqdm(df.iterrows()):
    if not row['Address'] == 'Multiple location':
        target_name = row['Address'] + ', ' + 'Chicago'
        gmaps_output = gmaps.geocode(target_name)
        if gmaps_output:  # 결과가 있는 경우에만 처리
            location_output = gmaps_output[0].get('geometry')
            lat.append(location_output['location']['lat'])
            lng.append(location_output['location']['lng'])
        else:
            # 결과가 없는 경우에 대한 처리
            lat.append(np.nan)
            lng.append(np.nan)
            print("No geocode results found for:", target_name)
    else:
        lat.append(np.nan)
        lng.append(np.nan)

 

이런 결과가 표시됐다.

34it [00:04,  7.86it/s]
No geocode results found for: 15 N. Milwaukee Ave., Chicago
50it [00:07,  6.85it/s]

 

찾아보니 15 N. Milwaukee Ave., Chicago는 정말로 존재하지 않는다. 페이지에 직접 가서 확인해보니 주소가 다르다는 걸 발견했다.

https://www.chicagomag.com/Chicago-Magazine/November-2012/Best-Sandwiches-in-Chicago-Paramount-Room-Paramount-Reuben/

 

33. Paramount Room Paramount Reuben

Briny lean brisket, kraut, and melted Gruyère neatly packaged between two thick slices of toasted marble rye

www.chicagomag.com

페이지를 들어가보면 해당 부분이 $13. 415 N. Milwaukee Ave., 312-829-6300, ...으로 표시되어 있다.

즉 앞부분의 '4'가 잘못 잘린 것이다. 왜 그럴까? 정규표현식을 다시 확인해봤다.

tmp_split = ['', '$6. Multiple location', ' dawalikitchen.com']

tmp_string = re.search('\$\d+\.(\d+)?', tmp_split[1]).group()
tmp_split[1][len(tmp_string)+2:]

# 'ultiple location'

 

'\$\d+\.(\d+)?'라는 정규표현식은 $ + 숫자(하나 이상) + . + 숫자(하나 이상, 있어도 되고 없어도 됨)인 str을 찾는 것이다. 그런데 이상하게도 저렇게 하면 $6. 뒤의 공백문자와 M(' M)을 잘라버린다. 이번엔 다른 방식으로 정규표현식을 수정해보았다.

tmp_string = re.search('\$\d+(\.\d+)?', tmp_split[1]).group()
tmp_split[1][len(tmp_string)+2:]

# 'Multiple location'

 

 

$ + 숫자(하나 이상) + (온점(' . ' ) + 숫자(하나 이상, 있어도 되고 없어도 됨)) 이란 식으로 묶어 주었다. 그러니 제대로 표시된다.

수정된 코드로 다시 bs4를 돌려 dataframe을 다시 만들어주었다.

lat = []
lng = []

for idx, row in tqdm(df.iterrows()):
    if not row['Address'] == 'Multiple locations':
        target_name = row['Address'] + ', ' + 'Chicago'
        gmaps_output = gmaps.geocode(target_name)
        if gmaps_output:  # 결과가 있는 경우에만 처리
            location_output = gmaps_output[0].get('geometry')
            lat.append(location_output['location']['lat'])
            lng.append(location_output['location']['lng'])
        else:
            # 결과가 없는 경우에 대한 처리
            lat.append(np.nan)
            lng.append(np.nan)
            print("No geocode results found for:", target_name)
    else:
        lat.append(np.nan)
        lng.append(np.nan)

정상적으로 lat과 lng과 반영되었다!

문제를 해결했다. 다시 시작!

 

*** 다시 지도 시각화 ***

4. lat과 lng라는 컬럼을 만들어준다.

 

5. 결과를 바탕으로 지도에 표시해본다. folium.Map을 이용한다.

mapping = folium.Map(location = [41.8781136, -87.6297982], zoom_start = 11)

for idx, row in df.iterrows():
    if not row['Address'] == 'Multiple locations':
        folium.Marker([row['lat'], row['lng']], popup = row['Cafe']).add_to(mapping)

mapping

잘 표시되었다!

6. 기존에 배웠던 부분을 바탕으로 툴팁, 아이콘을 더 표시해보자.

mapping = folium.Map(location = [41.8781136, -87.6297982], zoom_start = 11)

for idx, row in df.iterrows():
    if not row['Address'] == 'Multiple locations':
        folium.Marker([row['lat'], row['lng']], popup = row['Cafe'], tooltip=row['Menu'], icon = folium.Icon(
            icon='coffee',
            prefix = 'fa')
        ).add_to(mapping)

mapping

아이콘에 마우스를 올리면 메뉴가 나타나고, 아이콘을 클릭하면 카페 이름이 표시된다.