Python 잔잔한 팁

Soo Im·2021년 6월 11일
0

잔잔한 팁

목록 보기
2/5

1. colab에서 한글 폰트가 깨질 때

관련 포스트가 아주 많아서 이것저것 시도해보았지만 결국 먹힌 것은 이 포스트밖에 없었다. 친절한 작성자분께 감사를 표하며... 미래의 나를 위해 여기에도 남겨둔다.

🤗 당황하지 마시오
이 방법은 seaborn이든 matplotlib이든 관계없다. 처음 검색할 땐 '어?? 난 seaborn 그림 그릴건데 왜 matplotlib 게시글만 있지?' 하고 seaborn 글을 찾아 한참 헤맸는데... 둘 다 똑같이 먹히니 걱정말고 따라하자.

STEP 1. 폰트를 설치한다

한글 폰트를 설치한다. 아래에 나와있는 건 나눔폰트.

!apt-get update -qq	# 요건 하던지 말던지
!apt-get install fonts-nanum* -qq

참고로 !pip install 등을 하면 나오는 긴~ 설치 결과를 굳이 보고 싶지 않다면 커맨드 맨 뒤에 &> /dev/null을 붙이면 된다.

STEP 2. 폰트 설치 경로를 확인한다

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',...]

STEP 3. 폰트를 지정한다

위에서 확인한 경로를 이용해 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로 설치하지 않고 폴더에 있는 걸 곧바로 쓰는 방법을 찾아봐야겠다.

STEP 4. 런타임을 다시 시작하고 실행한다

위의 단계를 마쳤어도 한글이 깨져서 나올 것이다. Ctrl+M을 눌러 런타임을 재시작한 뒤 코드를 재실행하면 정상적으로 작동한다!

2. df.pivot_table 했더니 없던 NaN이 생겼을 때

df.isnull().sum()을 출력해서 분명 Null이 없는 것을 확인했는데 df.pivot_table을 했더니 갑자기 Null이 생기는 경우가 있다. 이건 pivot_table(index=..., columns=..., values=...)에서 indexcolumns에 해당하는 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는 그 indexcolumns을 가지는 값 중 어떤 값을 연산할 것인지를 의미한다. 아무 설정을 하지 않으면 연산은 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으로 처리된 것을 볼 수 있다.

3. correlation matrix에서 correlation 큰/작은 쌍을 순서대로 보고 싶을 때

여러 변수간의 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가 반환된다.

0개의 댓글