본문 바로가기
AI SCHOOL/TIL

[DAY 25] 서울시 코로나19 EDA - crosstab, str.contains와 isin, 데이터 시각화

2023. 2. 1.

DAY 24에 이어 서울시 코로나19 확진자 EDA를 했다.

다양한 분석을 하며 pandas에 더 익숙해지고 시각화에 대한 감을 잡은 것 같다.

pandas의 crosstab

두 개의 변수에 대한 빈도수, 빈도 비율 구하기

# 연도, 퇴원현황 빈도수 구하기
pd.crosstab(index=df['연도'], columns=df['퇴원현황'])

 

# pd.crosstab 으로 연도, 퇴원현황 두 개의 변수에 대한 빈도 비율 구하기
pd.crosstab(index=df['연도'], columns=df['퇴원현황'], normalize=True) * 100

각각 빈도수와 빈도 비율을 구한다.
normalize=True로 전체 value에 대한 비율을 구해준다. 모두 합하면 100%가 된다.

numbernumrate
빈도수와 빈도 비율

위와 같은 데이터 프레임이 반환된다.

연도, 월에 대한 빈도수 시각화

ym = pd.crosstab(index=df['연도'], columns=df['월'])
ym

yearmonth

각 연도에 대한 월별 확진자 수를 보여준다.

ym.plot(kind='bar');

bar plot을 그리면 아래와 같다.

ymbar

연도, 월별 막대를 그렸으나 직관적이지 않다.
아래와 같이 바꾸어 그려보자.

ym.T.plot(kind='bar');

전치행렬을 구하고 bar plot을 그린다.

ymonth2

전치를 한 후 그래프를 그려보니 색도 2가지 뿐이며 매우 직관적이다.
막대그래프 시각화를 할 땐 색상을 3가지 이하로 하는 것이 추천된다고 한다.

거주구, 연도월에 대한 빈도수 시각화

gu_ym = pd.crosstab(index=df['거주구'], columns=df['연도월'])
gu_ym

아래와 같이 구별, 월별 확진자 수를 확인할 수 있다.

gumon

위 데이터를 시각화해보자.

gu_ym.style.background_gradient()

style.background_gradient()는 빈도수를 시각화한다.

bgcolor
색상 비교

컬럼별로 수치를 비교하여 수치가 높을수록 진한 색상으로 표현하는 시각화 방법이다.

gu_ym.T.style.background_gradient()

전치행렬을 이용하여 시각화하면

bgcolor2

서울시 모든 구에서 시간이 흐름에 따라 코로나 확진자 수가 늘어나 2021년 12월에 정점이 된 것을 확인할 수 있다.

Boolean Indexing

여러 조건 비교하기

# 강남구에서 일요일에 확진된 데이터만 찾기
df.loc[(df['거주구'] == '강남구') & (df['요일명'] == '일'), ['거주구', '요일명']]

두 조건을 &를 이용하여 연결했다.
결과는 아래와 같다.

gangnamsun

 

# 거주구가 강남구이며, 여행력이 일본인 데이터 찾기
# 변수에 대입하여 사용하는 방법
gangnam =df['거주구'] == '강남구'
japan = df['여행력'] == '일본'
df.loc[gangnam & japan, ['거주구', '여행력']]

각 조건을 변수에 대입하여 loc에서 인덱싱할 때 사용하였다.
결과는 아래와 같이 나온다.

gangnamja


str.contains, isin활용하기

df.loc[df['거주구'].str.contains("강남구|서초구|송파구"), '거주구'].value_counts()
df.loc[df['거주구'].str.contains("강남구" or "서초구" or "송파구"), '거주구'].value_counts()
df.loc[df['거주구'].isin(["강남구", "서초구", "송파구"]), '거주구'].value_counts()

위의 3줄 각각의 차이를 이해해야한다.
첫번째 줄은 거주구에 강남구 또는 서초구 또는 송파구라는 문자열을 포함하면 True가 반환되며
두번째 줄은 첫번째 줄과 같아 보이지만 강남구라는 문자열을 포함하면 True가 반환된다.
세번째 줄은 강남구 또는 서초구 또는 송파구와 일치하면 True가 반환된다.

여러 문자열에 대해 일치 여부를 확인하고 싶은 경우 isin을 사용하고 포함 여부를 확인하고 싶은 경우에는 str.contains를 사용한다는 점과, str.contains를 사용할 시 or를 쓰지 않고 |를 사용해야 원하는 결과를 얻을 수 있다는 점을 유의해야한다.

국내발생, 해외유입 시각화

거주구별 국내발생과 해외유입 확진자 수를 구한다.

gu_oversea = pd.crosstab(df['거주구'], df['국내해외'])
gu_oversea.head()

상위 5개 행이 출력된다.

oversea

위 데이터에서 거주구별 국내 발생 대비 해외 유입 비율을 구하여 해외비율 컬럼으로 추가한다.

gu_oversea['해외비율'] = gu_oversea['해외'] / gu_oversea['국내']
gu_oversea.head()

다시 데이터를 확인해보면

oversea2

빈도수를 확인하여 예상할 수 있었지만, 실제로 계산해본 결과 해외비율이 굉장히 낮다.

그래프를 통해 시각적으로 확인해보자.

gu_oversea[["국내", "해외"]].sort_values("국내").plot(kind="barh", stacked=True);

plot의 kind='barh'와 stacked=True를 사용하여 중첩 수평막대그래프를 그리면 아래와 같다.

eachgu

결과 그래프는 잘 그려졌으나 해외의 비율이 너무 낮아서 직관적이지 않다.

다른 방법으로 시각화한다.

gu_oversea.loc[:, ['국내', '해외']].sort_values('해외', ascending=False).plot(kind='bar', subplots=True);

서브플롯을 활용하는 방법이다.

eachgu2

해외 확진자 수 내림차순으로 막대그래프를 그렸으며 subplots=True로 직관적인 결과를 얻었다.

pivot_table과 groupby()

위에서 사용한 crosstab()의 소스코드를 보면 내부가 pivot_table() 활용으로 되어있다.
즉, pandas의 crosstab()은 pivot_table()을 사용하기 쉽게 한번 더 wrapping해놓은 기능이다.
crosstab()에 비해 pivot_table()을 사용하면 더 많은 기능을 사용할 수 있다.

또한 pivot_table()의 내부는 groupby()로 되어있다.
그러므로 groupby()를 익히면 구하고자 하는 값을 대부분 구할 수 있다.

반응형

댓글