EDA | 서울시 지하철 호선별 유무임 승하차 데이터 분석

소리·2024년 1월 30일
0

1번 중복 제거

  • 조건1 : 각 Row(행) 중 내용이 모두 똑같은(중복되는) Row(행)이 있다면 가장 앞의 Row(Index가 가장 낮은 Row(행))는 남기고 나머지 중복되는 Row(행)를 삭제
#내 풀이
df_target.drop_duplicates(keep='first', inplace=True)



  • 조건2 : 각 Row(행) 중 ['사용월', '호선명', '지하철역'] 의 내용이 모두 똑같은(중복되는) Row(행)이 있다면 가장 앞의 Row(Index가 가장 낮은 Row(행))에 ['유임승차인원', '무임승차인원', '유임하차인원', '무임하차인원'] 각각 합한 값을 입력하고, 나머지 ['사용월', '호선명', '지하철역'] 의 내용이 중복되는 Row(행)를 삭제
#내 풀이
df_target[['유임승차인원', '무임승차인원', '유임하차인원', '무임하차인원']] = df_target.groupby(['사용월', '호선명', '지하철역'])[['유임승차인원', '무임승차인원', '유임하차인원', '무임하차인원']].transform('sum')
df_target.drop_duplicates(subset=['사용월', '호선명', '지하철역'], keep='first', inplace=True)
#모범답안
target_cols = ['유임승차인원', '무임승차인원', '유임하차인원', '무임하차인원']
target_values = df_target[df_target.duplicated(subset=['사용월', '호선명', '지하철역'])].iloc[:, :3].drop_duplicates()
for _, (month, line, station) in target_values.iterrows():
    df_temp = df_target[(df_target.사용월==month)&(df_target.호선명==line)&(df_target.지하철역==station)]
    df_target.loc[df_temp.index[0], target_cols] = df_temp[target_cols].sum()
    df_target.drop(df_temp.index[1:], inplace=True)



  • 조건3 : '호선명' Column(열)의 Data가 '9호선2~3단계' 또는 '9호선2단계'라면 이를 '9호선'으로 변경

  • 조건4 : 지하철역' Column(열)의 Data에 괄호('(', ')')가 있다면, 괄호 안의 내용과 괄호 자체를 모두 삭제

  • 조건5 : '지하철역' Column(열)의 Data가 '신천'이라면 '잠실새내'로 변경

#내풀이

df_target.loc[df_target['호선명'] == '9호선2~3단계', '호선명'] = '9호선'
df_target.loc[df_target['호선명'] == '9호선2단계', '호선명'] = '9호선'

#조건2
df_target['지하철역'] = df_target['지하철역'].apply(lambda col : col.split('(')[0])

#조건3
df_target.loc[df_target['지하철역'] == '신천', '지하철역'] = '잠실새내'

#모범답안
ef change_line_name(line_name):
    line_name = '9호선' if line_name in ['9호선2~3단계', '9호선2단계'] else line_name
    return line_name

def change_station_name(station_name):
    station_name = station_name[:station_name.find('(')] if '(' in station_name else station_name
    station_name = '잠실새내' if station_name == '신천' else station_name
    return station_name

df_target.지하철역 = df_target.지하철역.apply(change_station_name)
df_target.호선명 = df_target.호선명.apply(change_line_name)

🔎 모범답안은 함수로 만들어서 풀었다



  • 조건6 : incheon_station_list에 있는 역들의 '호선명'을 '7호선'에서 '7호선 인천'으로 변경
  • 조건7: '지하철역' Column(열)의 Data에 괄호('(', ')')가 있다면, 괄호 안의 내용과 괄호 자체를 모두 삭제
#내 풀이
incheon_station_list = ['까치울', '부천종합운동장', '춘의', '신중동', '부천시청', '상동', '삼산체육관', '굴포천', '부평구청', '산곡', '석남']

df_target['호선명'] = df_target.apply(lambda row : '7호선 인천' if row['지하철역'] in incheon_station_list else row['호선명'], axis=1)

#모범답안 
df_target.loc[df_target[df_target.지하철역.isin(incheon_station_list)].index, '호선명'] = '7호선 인천'



2번 원하는 정보 얻기

  • 조건1: 2022년 6월 기준 각 지하철 역의 [유임승차인원, 무임승차인원, 유임하차인원, 무임하차인원] 을 구하라

  • 조건2: 환승역(한 지하철역에 여러개의 호선이 있는 역)이 있다면 합산

  • 조건3: Index와 Column은 아래와 같이 지정
    - Index: '지하철역'
    - Column: ['유임승차인원', '무임승차인원', '유임하차인원', '무임하차인원']

  • 조건4 : Index 기준 오름차순으로 정렬

#내풀이
#조건1 202206 기준
df_2206 = df_target.loc[df_target['사용월'] == 202206, :]

#조건2 환승역 합산
df_result = pd.pivot_table(df_2206, index = '지하철역', values = ['유임승차인원', '무임승차인원', '유임하차인원', '무임하차인원'], aggfunc = 'sum')
#모범답안
df_result = df_target.iloc[:, 1:-1][df_target.사용월 == 202206].groupby(['지하철역']).sum()
df_result.sort_index(axis=0, ascending=True, inplace=True)



  • 조건5: 2022년 6월 기준 각 지하철 역의 호선의 수를 구하고, 호선의 수가 3개 이상인 역만 보여주세요.

  • 조건6: '호선수' Column(열)을 만들어 해당 역의 호선 수를 입력

  • 조건7: Index와 Column은 아래와 같이 지정
    - Index: '지하철역'
    - Column: ['호선수']

  • 조건8: '호선수' Column(열)을 기준으로 내림차순 정렬하고, '호선수'가 같다면 Index('지하철역')를 기준으로 내림차순 정렬

#내 풀이
df_counts = pd.pivot_table(df_2206, index = '지하철역', values='호선명', aggfunc = 'count')
df_counts.columns = ['호선수']
df_result = df_counts[df_counts['호선수'] > 2]
df_result = df_result.sort_values(by=['호선수', '지하철역'], ascending=[False, False])
#모범답안 풀이
df_result = df_target.iloc[:, 1:-1][df_target.사용월 == 202206]
df_result = df_result.groupby(['지하철역']).count()
df_result = df_result.iloc[:, :1]
df_result.rename({'호선명': '호선수'}, axis=1, inplace=True)
df_result.sort_values(by=['호선수', '지하철역'], ascending=[False, False], inplace=True)
df_result = df_result[df_result['호선수'] >= 3]



2-2

  • 조건1: 위 2-2를 참고하여 아래와 같이 '호선수'를 구하세요.
    - 2022년 6월 기준 각 지하철 역의 호선의 수를 구하고, 호선의 수가 3개 이상인 역만 보여주세요.
    - '호선수' Column(열)을 만들어 해당 역의 호선 수를 입력해주세요.

  • 조건2: 2022년 6월 기준 '환승호선' Column(열)을 만들어 아래와 같이 해당 역의 환승 가능 호선을 나열해주세요.
    - 환승 호선들은 ', '(쉼표+띄어쓰기)로 구분되는 string입니다.
    - 환승 호선들은 오름차순으로 정렬 후 나열해주세요.
    - 위 예시를 참고해주세요.

  • 조건3: Index와 Column은 아래와 같이 지정해 주세요.
    - Index: '지하철역'
    - Column: ['호선수', '환승호선']

  • 조건4: '호선수' Column(열)을 기준으로 내림차순 정렬하고, '호선수'가 같다면 '환승호선' Column(열)을 기준으로 오름차순 정렬해주세요.

#내풀이
#조건1
df_result2 = df_result.copy()
#조건2
df_trans = pd.DataFrame(df_2206.groupby(by='지하철역')['호선명'].unique())

df_merge = pd.merge(df_result2, df_trans, how = 'inner', left_index=True, right_index=True)
df_merge.rename(columns={'호선명': '환승호선'}, inplace=True)
df_merge['환승호선'] = df_merge['환승호선'].apply(lambda x: ', '.join(map(str, x)))
df_result = df_merge.sort_values(by=['호선수', '환승호선'], ascending=[False, True])
#모범답안
df_temp = df_target.iloc[:, 1:3][df_target.사용월 == 202206]

df_temp_01 = df_temp.groupby(['지하철역']).count()
df_temp_01.rename({'호선명': '호선수'}, axis=1, inplace=True)

df_temp_02 = df_temp.groupby(['지하철역']).agg(lambda x: ', '.join(sorted(list(x))))
df_temp_02.rename({'호선명': '환승호선'}, axis=1, inplace=True)

df_result = pd.concat([df_temp_01, df_temp_02], axis=1)

df_result.sort_values(by=['호선수', '환승호선'], ascending=[False, True], inplace=True)
df_result = df_result[df_result['호선수'] >= 3]



  • 조건1: 위 2-2를 참고하여 아래와 같이 '호선수'를 구하세요.
    - 2022년 6월 기준 각 지하철 역의 호선의 수를 구하고, 호선의 수가 2개 이상인 역만 보여주세요.
    - '호선수' Column(열)을 만들어 해당 역의 호선 수를 입력해주세요.

  • 조건2: 2022년 6월 기준 ['유임승하차율', '무임승하차율', '승하차율'] Column(열)을 만들어 아래와 같이 각각의 승하차율을 구하세요.
    - 유임승하차율 = 유임승차인원 / 유임하차인원 100
    - 무임승하차율 = 무임승차인원 / 무임하차인원
    100
    - 승하차율 = (유임승차인원 + 무임승차인원) / (유임하차인원 + 무임하차인원) * 100
    - 각각의 승하차율은 소숫점 셋째자리에서 반올림하여 둘째자리까지 표기합니다.
    - '무임승하차율'이 '승하차율'보다 크면서, '무임승하차율'이 102 이상인 역만 보여주세요.
    - 위 예시를 참고해주세요.

  • 조건3: Index와 Column은 아래와 같이 지정해 주세요.
    - Index: '지하철역'
    - Column: ['호선수', '유임승하차율', '무임승하차율', '승하차율']
  • 조건4: '호선수' Column(열)을 기준으로 내림차순 정렬하고, '호선수'가 같다면 '무임승하차율' Column(열)을 기준으로 내림차순 정렬해주세요.
#조건1
df_counts = pd.pivot_table(df_2206, index = '지하철역', values='호선명', aggfunc = 'count')
df_counts.columns = ['호선수']
df_counts = df_counts[df_counts['호선수'] >= 2]
df_counts

df_base = pd.pivot_table(df_2206, index = '지하철역', values = ['유임승차인원', '무임승차인원', '유임하차인원', '무임하차인원'], aggfunc = 'sum')
df2 = pd.merge(df_counts, df_base, left_index=True, right_index=True)
df2

def cal_rate(row):
    rate_paid = row['유임승차인원'] / max(row['유임하차인원'], 1) * 100  # 유임승하차율
    rate_unpaid = row['무임승차인원'] / max(row['무임하차인원'], 1) * 100  # 무임승하차율
    rate_f = (row['유임승차인원'] + row['무임승차인원']) / max(row['유임하차인원'] + row['무임하차인원'], 1) * 100  # 승하차율

    return rate_paid, rate_unpaid, rate_f

df2[['유임승하차율', '무임승하차율', '승하차율']] = df2.apply(cal_rate, axis=1).apply(lambda x: pd.Series(x)).apply(lambda x : round(x,2))


df_2_4 = df2[((df2['무임승하차율'] > df2['승하차율']) & (df2['무임승하차율'] >= 102))]
df_2_4 = df_2_4[df_2_4['호선수'] >= 2]
df_2_4 = df_2_4[['호선수', '유임승하차율', '무임승하차율', '승하차율']]
df_result = df_2_4.sort_values(by=['호선수', '무임승하차율'], ascending = [False, False])
#모범답안
# 2-4
df_temp = df_target.iloc[:, 1:3][df_target.사용월 == 202206]

df_temp_01 = df_temp.groupby(['지하철역']).count()
df_temp_01.rename({'호선명': '호선수'}, axis=1, inplace=True)

df_temp = df_target.iloc[:, :-1][df_target.사용월 == 202206]

df_temp_02 = df_temp.groupby(['지하철역']).sum()

df_temp_02['유임승하차율'] = round(df_temp_02.유임승차인원 / df_temp_02.유임하차인원 * 100, 2)
df_temp_02['무임승하차율'] = round(df_temp_02.무임승차인원 / df_temp_02.무임하차인원 * 100, 2)
df_temp_02['승하차율'] = round((df_temp_02.유임승차인원 + df_temp_02.무임승차인원) / (df_temp_02.유임하차인원 + df_temp_02.무임하차인원) * 100, 2)
df_temp_02 = df_temp_02.iloc[:, 5:]

df_result = pd.concat([df_temp_01, df_temp_02], axis=1)
df_result = df_result[(df_result['호선수'] >= 2) & (df_result.무임승하차율 > df_result.승하차율) & (df_result.무임승하차율 > 102)]
df_result.sort_values(by=['호선수', '무임승하차율'], ascending=[False, False], inplace=True)



3번

  • 조건1: '유동인구증감률' Column(열)을 만들어 2022년 1월 대비 2022년 6월의 유동인구 증가율을 입력하세요.
    - 유동인구 = '유임승차인원' + '무임승차인원' + '유임하차인원' + '무임하차인원'
    - 유동인구 증감률 = (2022년 6월의 유동인구 / 2022년 1월의 유동인구 - 1) * 100
    - 유동인구 증감률은 소숫점 셋째자리에서 반올림하여 둘째자리까지 표기합니다.
    - 유동인구가 감소한(유동인구 증감률이 0보다 작은) 역만 보여주세요.

  • 조건2: 2022년 1월 이후에 역이 신설되어 2022년 1월 유동인구 Data가 없는 경우 제외하고 계산하세요.
    - '신림선'의 역들은 2022년 5월에 운영 시작하였습니다.

  • 조건3: 위 1-5를 참고하여 '호선명' Column(열) Data가 '7호선 인천'인 경우는 제외하고 구하세요.
    - 앞서 언급하였다시피 Data에 오류가 있는 것으로 추정되어 제외합니다.

  • 조건4: Index와 Column은 아래와 같이 지정해 주세요.
    - Index: '지하철역'
    - Column: ['유동인구증감률']

  • 조건5: '유동인구증가율' Column(열)을 기준으로 내림차순 정렬하세요.

#조건1
df_2201 = df_target[df_target['사용월'] == 202201]
df_2206 = df_target[df_target['사용월'] == 202206]

import warnings
warnings.filterwarnings("ignore")

#지하철별로 합치기
def bystation(df):
    df[['유임승차인원', '무임승차인원', '유임하차인원', '무임하차인원']] = df.groupby(['지하철역'])[['유임승차인원', '무임승차인원', '유임하차인원', '무임하차인원']].transform('sum')
    df.drop_duplicates(subset=['지하철역'], keep='first', inplace=True)
    
    return df

bystation(df_2206)
bystation(df_2201)

#유동인구
def get_floating(row):
    return row['유임승차인원'] + row['무임승차인원'] + row['유임하차인원'] + row['무임하차인원']

df_2206['유동인구'] = df_2206.apply(get_floating, axis=1) #6월 유동인구
df_2201['유동인구'] = df_2201.apply(get_floating, axis=1) #1월 유동인구

#조건2, 3
def delete_line(df, line): #7호선 인천, 신림선 line에 삽입하면 됨
    df = df.drop(df[df['호선명'] == line].index, axis=0, inplace=True)

#적용하기
delete_line(df_2206, '7호선 인천')
delete_line(df_2206, '신림선')
delete_line(df_2201, '7호선 인천')

pivot_2201 = pd.pivot_table(df_2201, index = '지하철역', values = '유동인구', aggfunc='sum')
pivot_2201.columns = ['1월 유동인구']
pivot_2206 = pd.pivot_table(df_2206, index = '지하철역', values = '유동인구', aggfunc='sum')
pivot_2206.columns = ['6월 유동인구']

pivot_f = pd.concat([pivot_2206, pivot_2201], axis=1)
pivot_f['유동인구증감률'] = round((pivot_f['6월 유동인구'] / pivot_f['1월 유동인구'] -1) * 100, 2)


df_result = pivot_f[pivot_f['유동인구증감률'] < 0]
df_result.drop(columns = ['6월 유동인구', '1월 유동인구'], inplace=True)
df_result = df_result.sort_values(by='유동인구증감률', ascending=False)
#모범답안
# 3-1
df_temp = df_target[df_target.사용월.isin([202201, 202206])&(df_target.호선명!='7호선 인천')].iloc[:, :-1]
df_temp['유동인구'] = df_temp.apply(lambda row: row.iloc[3:].sum(), axis=1)
df_temp = df_temp.groupby(['지하철역', '사용월']).sum()

station_names = df_temp.index.get_level_values(0).unique()
df_result = pd.DataFrame(columns=['유동인구증감률'], index=station_names)

for station_name in station_names:
    if df_temp.loc[station_name].유동인구.count() == 1:
        continue

    rate = round((df_temp.loc[(station_name, 202206), '유동인구'] / df_temp.loc[(station_name, 202201), '유동인구'] - 1) * 100, 2)
    df_result.loc[station_name, '유동인구증감률'] = rate

df_result.dropna(inplace=True)
df_result.sort_values('유동인구증감률', ascending=False, inplace=True)
df_result = df_result[df_result.유동인구증감률 < 0]

check_03_01(df_result)
df_result



###3-2번

df_3_2 = df_target.copy()
select_line = ['1호선', '2호선', '3호선', '4호선', '5호선', '6호선', '7호선', '8호선', '9호선']
#df_temp = df_target[df_target.호선명.isin([f'{i}호선' for i in range(1, 10)])] 내가 하고 싶었던 거!! 
df_3_2 = df_3_2[df_3_2['호선명'].isin(select_line)]

#그럼 지하철역 중 작업일자가 가장 낮은 날을 구하면 되지 않을까? 신설월을 구해야지
df_3_2.drop_duplicates(subset=['지하철역'], keep='last', inplace=True)

df_3_2['신설월'] = df_3_2['사용월']
df_3_2 = df_3_2[df_3_2['신설월'] != 201501]

df_result = df_3_2.loc[:, ['호선명', '지하철역', '신설월']]
df_result = df_result.sort_values(by=['호선명', '신설월', '지하철역'], ascending=[True, False, True]).reset_index(drop=True)
#모범답안
df_temp = df_target[df_target.호선명.isin([f'{i}호선' for i in range(1, 10)])]

all_months = sorted(df_temp.사용월.unique())
target_station = df_temp.apply(lambda row: (row.호선명, row.지하철역), axis=1).unique()

data_list = []
for line, station_name in target_station:
    target_months = sorted(df_temp[(df_temp.지하철역==station_name)].사용월.to_list())
    no_exist = [month for month in all_months if month not in target_months]

    if no_exist:
        data_list.append([line, station_name, target_months[0]])

df_result = pd.DataFrame(data_list, columns=['호선명', '지하철역', '신설월'])
df_result.sort_values(by=['호선명', '신설월', '지하철역'], ascending=[True, False, True], inplace=True)
df_result.reset_index(drop=True, inplace=True)
profile
데이터로 경로를 탐색합니다.

0개의 댓글