관련 포스트가 아주 많아서 이것저것 시도해보았지만 결국 먹힌 것은 이 포스트밖에 없었다. 친절한 작성자분께 감사를 표하며... 미래의 나를 위해 여기에도 남겨둔다.
🤗 당황하지 마시오
이 방법은 seaborn이든 matplotlib이든 관계없다. 처음 검색할 땐 '어?? 난 seaborn 그림 그릴건데 왜 matplotlib 게시글만 있지?' 하고 seaborn 글을 찾아 한참 헤맸는데... 둘 다 똑같이 먹히니 걱정말고 따라하자.
한글 폰트를 설치한다. 아래에 나와있는 건 나눔폰트.
!apt-get update -qq # 요건 하던지 말던지
!apt-get install fonts-nanum* -qq
참고로 !pip install
등을 하면 나오는 긴~ 설치 결과를 굳이 보고 싶지 않다면 커맨드 맨 뒤에 &> /dev/null
을 붙이면 된다.
import matplotlib.font_manager as fm # plot 폰트 매니저
# 전체 폰트 중에서 나눔 폰트 경로를 확인한다
sys_font=fm.findSystemFonts()
nanum_font = [f for f in sys_font if 'Nanum' in f]
nanum_font
위 코드를 실행하면 아래처럼 나눔 폰트 설치 경로가 나온다.
['/usr/share/fonts/truetype/nanum/NanumGothicLight.ttf',
'/usr/share/fonts/truetype/nanum/NanumBrush.ttf',
'/usr/share/fonts/truetype/nanum/NanumSquareRoundL.ttf',...]
위에서 확인한 경로를 이용해 plot 폰트를 지정한다.
import matplotlib as mpl
import matplotlib.pyplot as plt
font_location = '/usr/share/fonts/truetype/nanum/NanumSquareRoundEB.ttf' # 여기에 원하는 폰트 경로를 넣는다
font_name = fm.FontProperties(fname=font_location).get_name()
plt.rc('font', family=font_name)
mpl.rcParams['axes.unicode_minus'] = False # minus(-) 기호가 깨지는 것을 방지
fm._rebuild() # 이걸 안 하면 폰트 설정이 안 된다. 왜인지는 잘 모르겠다...
🤨 그냥 폴더에 직접 폰트 집어넣으면 안되남?
폴더에 직접 NanumSquareRoundL.ttf 를 집어넣고 그 경로를font_location
에 준다면 설치할 필요가 없겠지!만! 이상하게도 그 방법은 먹히지 않는다. 적어도 위에 내가 적어둔 방법으로는 그렇다.
매번 폰트를!apt
로 설치하지 않고 폴더에 있는 걸 곧바로 쓰는 방법을 찾아봐야겠다.
위의 단계를 마쳤어도 한글이 깨져서 나올 것이다. Ctrl+M을 눌러 런타임을 재시작한 뒤 코드를 재실행하면 정상적으로 작동한다!
df.pivot_table
했더니 없던 NaN이 생겼을 때df.isnull().sum()
을 출력해서 분명 Null이 없는 것을 확인했는데 df.pivot_table
을 했더니 갑자기 Null이 생기는 경우가 있다. 이건 pivot_table(index=..., columns=..., values=...)
에서 index
와columns
에 해당하는 value
가 없을 때 생기는 문제이다. (이게 도대체 무슨 소리인가🙄) 이 글에 구체적인 예시가 나와있는데 옮겨보자면 다음과 같다.
>> purchase_data
>>
date customer_id purchase_qty
0 01/01 id1 12
1 01/01 id2 5
2 01/02 id1 4
3 01/03 id1 7
>> purchase_data.pivot_table(index='date', columns='customer_id', values='purchase_qty', agg_func=np.sum)
>>
customer_id id1 id2
date
01/01 12 5
01/02 4 NaN
01/03 7 NaN
index
는 문자 그대로 pivot table의 index를 가리키고 columns
는 그 pivot table에서 사용할 열의 기준을 나타낸다. 그리고 values
는 그 index
와 columns
을 가지는 값 중 어떤 값을 연산할 것인지를 의미한다. 아무 설정을 하지 않으면 연산은 values
의 평균값이고, agg_func
옵션을 사용하면 합, 곱 등의 연산도 할 수 있다.
위의 예시는 index
로 일자를, columns
로 고객 id를 선택했다. 그리고 일자와 id마다 (별 의미는 없지만 예시를 위해) 그 고객이 구매한 수량의 합을 구한다.
그런데 보다시피 01/02와 01/03에는 id2 고객이 물건을 주문하지 않았다. 그래서 해당 index
(01/02, 01/03)와 columns
(id2)에 해당하는 values
(purchase_qty)가 없으니 NaN으로 처리된 것이다. 그래서 원본 데이터에는 Null이 없었다 하더라도 pivot_table
을 사용하면 Null이 발생할 수 있는 것이다. 이 문제를 해결하려면 해당 값이 없을 때 대신 채울 값을 fill_value
옵션으로 넣어주면 된다.
>> purchase_data
>>
date customer_id purchase_qty
0 01/01 id1 12
1 01/01 id2 5
2 01/02 id1 4
3 01/03 id1 7
>> purchase_data.pivot_table(index='date', columns='customer_id', values='purchase_qty', agg_func=np.sum, fill_value=0)
>>
customer_id id1 id2
date
01/01 12 5
01/02 4 0
01/03 7 0
값이 없을 때 0으로 처리된 것을 볼 수 있다.
여러 변수간의 correlation을 한 번에 보기 위해 correlation matrix와 heatmap을 많이 사용한다.
출처: seaborn
다만 변수가 너무 많아지면 어느 쌍이 가장 상관이 높고 낮은지 보기 어렵다. 값을 직접 확인하는 방법은 다음과 같다.
# correlation matrix 만들기
corr_matrix = data.corr()
# 오름차순으로 정렬하되 중복되는 쌍은 제거하기
sort_corr = corr_matrix.unstack().sort_values().drop_duplicates()
# 작은 값 순서대로 10쌍 출력
sort_corr[:10]
unstack()
은 matrix 안의 값을 시리즈로 변환해주고 sort_values()
는 시리즈 내의 값을 오름차순으로 정렬해준다. 위에서 drop_duplicates()
를 하지 않으면 아래처럼 순서만 바뀐 동일한 쌍이 나와 값을 확인하기 어렵다.
A B -0.7
B A -0.7
A D -0.6
D A -0.6
거꾸로 내림차순으로 정렬할 때는 sort_values(ascending=False)
로 두면 된다. 다만 이 경우에는 A A, B B, C C,...와 같이 자기 자신의 correlation 쌍이 먼저 나오게 되므로 sort_corr[5:]
처럼 변수의 개수만큼 건너뛰고 출력해야 한다.
보통
unstack()
은 multiIndex를 해소하는 용도로 사용된다. 이 블로그에 예시가 아주 잘 나와있다. 지금 우리의 상황처럼 multiIndex가 아닌 pd.DataFrame을unstack()
하면 pd.Series가 반환된다.