판다스 공부 중 알 수 없는 코드를 발견했다.

df['시작_투여량'], df['마지막_투여량'] = df['투여량'].str.split(' - ', 1).str

하나의 열에서 ‘ - ‘ 를 기준으로 문자열을 나눠서 각각 다른 열에 담는 코드였다.
그런데 마지막에 붙는 .str 이 어떤식으로 동작하는지 이해 할 수 없었다.

그런데 판다스에서 str은 여러 스트링 관련 함수를 내장하고 있는 녀석이라
저렇게 .str만 똑 떼서 사용하는 경우는 처음봤고 왜 저게 동작하는지 이해 할 수 없었다.

그래서 조사를 해봤다.

위의 코드에서 우변만 떼서 타입이랑 내용을 확인하면

print(type(insuline_clean['투여량'].str.split(' - ', 1).str));
print(insuline_clean['투여량'].str.split(' - ', 1).str);

# Result
<class 'pandas.core.strings.accessor.StringMethods'>
<pandas.core.strings.accessor.StringMethods object at 0x00000236C1D49060>

이렇게 나온다
하지만 <class ‘pandas.core.strings.accessor.StringMethods’>
이 클래스에 대한건 구글링해도 딱히 나오지 않았다.

그래서 .str을 떼고 타입이랑 내용을 확인하니까

print(type(insuline_clean['투여량'].str.split(' - ', 1)));

# Result
<class 'pandas.core.series.Series'>

<class ‘pandas.core.series.Series’> 타입이라고 한다.

그렇다면

type(insuline_clean['투여량'].str.split(' - ', 1).str) == pd.core.series.Series.str);
# print
True

이렇게 된다!

그래서 판다스 문서에서 pandas.Series.str 부분을 찾아보니

Vectorized string functions for Series and Index.

이렇게 설명 딱 한줄이다.

결국 벡터라이즈된 스트링이라는 말.

여기서 벡터화는 간단하게 이야기해서 배열을 다중배열로 만드는 것.

# Vectorise
[0,1,2,3,4,5]
요딴걸

[[0,1,2]
[3,4,5]]
요딴식으로

근데 이렇게 벡터화를 시키면 장점이
동시에 여러가지 연산을 더 빠르게 처리할 수 있다고 한다.
왜 그런지는 잘 모르겠다.
아무튼 그런이유로 pandas.Series.str 메소드들을 사용하는 듯 하다.

처음으로 돌아와서 결국 마지막에 .str 이 하는일은

Series 투여량
[시작_투여량_0, 마지막_투여량_0]
[시작_투여량_1, 마지막_투여량_1]
[시작_투여량_2, 마지막_투여량_2]
[시작_투여량_3, 마지막_투여량_3]
[시작_투여량_4, 마지막_투여량_4]

요딴식으로 하나의 줄줄이 비엔나로 묶여있던 결과값이
.str 로 타입이 변환이 되면서

# 이해를 돕기위한 예시입니다.
# 실제로 어떻게 되는지는 잘 모름...

Series 시작투여량   Series 마지막투여량
[시작_투여량_0]     [마지막_투여량_0]
[시작_투여량_1]     [마지막_투여량_1]
[시작_투여량_2]     [마지막_투여량_2]
[시작_투여량_3]     [마지막_투여량_3]
[시작_투여량_4]     [마지막_투여량_4]

요딴식으로 나눠주는 것 같다.

저렇게 이중 배열이 되면

list_1,list_2 = [[1, 2, 3],[4,5,6]];
print('list_1 :', list_1);
print('list_2 :', list_2);
# print
list_1 : [1, 2, 3]
list_2 : [4, 5, 6]

파이썬에서는 요렇게 두개의 변수에 나눠 담는게 가능하기 때문에

df['시작_투여량'], df['마지막_투여량'] = df['투여량'].str.split(' - ', 1).str

이 코드가 .str로 인해 동작하게 된다.

!!!중요!!!

그런데 이렇게 말고 더 간단하게 하는 방법이 있다.

insuline_clean[['시작_투여량','마지막_투여량']] = insuline_clean['투여량'].str.split(' - ', n=1,expand=True);

이렇게 split 함수에 expand=True 를 넣어주면 DataFrame으로 반환을 해서
위의 코드처럼 DataFrame에 넣는게 가능하다.
개인적으로 이 방법이 더 직관적이라고 생각하고
속도도 미미…하게 더 빠르다.

Leave a comment