EDA 과제, 이게 최선입니까?

I'm Cape·2023년 6월 12일
0

아니요, 절대 최선이 아닙니다.
죄송합니다ㅠㅠ

문제 1: 혼란스럽게만 하는 변수와 함수

jupyter notebook에서 %who를 입력하면 변수 목록을 보여준다.
이번 과제에서 선언한 변수는 다음과 같다.
scope 내부에서 선언된 변수는 포함하지 않는 듯 하다.

ADDR_BUTTON
ADDR_INPUT
ADDR_LIST
ADDR_SUBMIT
ActionChains
BeautifulSoup
By
EDIYA_URL
SEOUL_SELECTOR
STARBUCKS_URL
ScrollOrigin
WebDriverWait
boxplot
count_by_distance
distances
dl_items
draw_scatter_by_gu
driver
dst_list
dst_list_series
dst_series
edi_close
edi_close_w_star
edi_df
edi_gangnam
edi_html
edi_lat
edi_lng
edi_target
elem
elems
expected_conditions
gangnam_distances
gangnam_dst_series
geopy
get_edi_frame
get_element
get_elements
get_gu
get_star_address
get_star_frame
get_star_name
googlemaps
gu
gu_list
gugun_selector
guguncd
guguncds
infos
koreanize_matplotlib
least_distances
li_items
list_initialized
np
pd
plt
result
scroll_frame
should_scroll
sns
soup
star_count_by_gu
star_df
star_gangnam
star_html
star_infos
star_lat
star_lng
star_target
total_df
tqdm
webdriver
  1. Selector을 상수로 선언하기 보다는,
    함수로 선언하여 사용하는 것이 나았을 듯 하다.
  2. elem, elems, result와 같은 변수는
    global scope에서 정의하기에는 위험하다.
    사실 global scope에는 변수가 없을수록 좋을 듯.
    생각보단 막지은 변수가 없다.
    작성하면서는 너무 막쓰는 거 같아서 스트레스가 했는데...

문제 2: 객체지향? 배째!

위와 같이 불안정한 변수 선언이 나오게 되는 이유는,
코드가 구조화되지 않았기 때문이다.

그냥 함수만 사용해서 코드를 짜면
(물론 이번 과제의 경우 함수도 잘 쓰지 않았다... 반성하자)
예를 들어 10개의 함수를 선언했다면,
재사용이 필요할 때 10개의 함수를 일일히 찾아야 한다.
시간에 쫓길 때에는 간단한 과정이라면 그냥 새로 쓰게 된다.
그러면 같은 일을 하는 코드가 2개가 생기게 되는 것이다.

객체지향을 활용했다면,
함수의 목적에 따라 분류가 되고,
scope 또한 지정되어 실수로 같은 변수명을 짓게될 가능성이 낮아진다.
python에는 js의 const 같은게 없나? 찾아봤지만 아직은 모르겠다.
아무튼, 객체지향을 적극적으로 활용해보자.

문제 3: 비효율의 끝판왕

def count_by_distance(meter, d_series, t_edi_df, get_raw=False):
    und_thresh = d_series[d_series < meter / 1000].sort_values()
    close_ratio = len(und_thresh) / len(t_edi_df) * 100
    if get_raw:
        return len(t_edi_df), len(und_thresh)
    return f'총 {len(t_edi_df)}개의 이디야 매장 중 {len(und_thresh)}개의 매장({close_ratio:.1f}%)이 {meter}m 거리에 스타벅스 매장이 있습니다.'

제일 맘에 안들었지만 맘이 급해서 지나간 함수.
1. Functions should do one thing. 이 함수는 2가지 이상의 일을 하고 있다.
2. Don't use flags as function parameters. flag를 parameter로 전달하지 말 것.

봤을 때 의문.
1. t_edi_df가 대체 뭔데? - target을 의도한 듯. 무의미하다 헷갈리게만 하고.
2. 즉 위 함수는 이디야 DataFrame만을 고려해서 만든 듯 하다.
그렇다면 class를 활용하여 global scope에서 제외해주는 것이 좋았을 듯.

아래와 같이 수정하였다. (수정하는데 너무 시간을 많이 썼다ㅠ)
더 수정할 사항이 보이지만 시간소요가 지나치니 그만둬야겠다.

class DistanceAnalyzer:
    def __init__(self, distance_series):
        self.distances = distance_series 
    
    def by_meter(self, meter_threshold):
        km_threshold = meter_threshold / 1000
        filtered_distances = self.distances[self.distances < km_threshold]
        filtered_ratio = len(filtered_distances) / len(self.distances) * 100
        return filtered_distances, filtered_ratio
    
    def by_meter_formatted(self, meter_threshold):
        f_distances, f_ratio = self.by_meter(meter_threshold)
        return f'총 {len(self.distances)}개의 이디야 매장 중 {len(f_distances)}개의 매장({f_ratio:.1f}%)이 {meter_threshold}m 거리에 스타벅스 매장이 있습니다.'

formatted_result = DistanceAnalyzer(dst_series).by_meter_formatted(100)
print(formatted_result)
profile
Impact

0개의 댓글