본문 바로가기
ML, DL/Data Analysis

[Pandas] Part 3. Dataframe smaller and faster, Dummy, Dates and times,

by Wordbe 2019. 10. 12.
728x90

21. Make Dataframe smaller, faster

object 타입 대신, category 타입 사용은 메모리 usage를 효율적으로 활용할 수 있게할 뿐만 아니라 시간도 빨라질 수 있습니다.

string(object)을 탐색하는 것보다, integer(category)탐색이 시간이 빠르기 때문입니다.

drinks.info() # + 의미: object가 무엇을 참조하느냐에 따라 9.2KB를 초과할 수 있다.

>>
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 193 entries, 0 to 192
Data columns (total 6 columns):
country                         193 non-null object
beer_servings                   193 non-null int64
spirit_servings                 193 non-null int64
wine_servings                   193 non-null int64
total_litres_of_pure_alcohol    193 non-null float64
continent                       193 non-null object
dtypes: float64(1), int64(3), object(2)
memory usage: 9.2+ KB

drinks.info(memory_usage='deep')
>>
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 193 entries, 0 to 192
Data columns (total 6 columns):
country                         193 non-null object
beer_servings                   193 non-null int64
spirit_servings                 193 non-null int64
wine_servings                   193 non-null int64
total_litres_of_pure_alcohol    193 non-null float64
continent                       193 non-null object
dtypes: float64(1), int64(3), object(2)
memory usage: 30.5 KB
drinks.memory_usage()
drinks.memory_usage(deep=True)
drinks.memory_usage(deep=True).sum()

어떻게 공간을 줄일 수 있을까요?(smaller and then faster)

sorted(drinks.continent.unique())
drinks.continent.head()

drinks['continent'] = drinks.continent.astype('category') # dtype을 object대신 category로 변경

# 바뀐 것 확인
drinks.dtypes
drinks.continent.head()
drinks.continent.cat.codes.head()
drinks.memory_usage(deep=True) # category 타입이 object타입보다 더 공간을 적게 차지한다.

예외

drinks['country'] = drinks.country.astype('category')
# 모든 country 값은 각각 다른 string이다. country 타입이 string(object)에서 integer(category)로 바뀌면서, 타입 크기는 줄었지만,
# 193가지의 다른 string에 대한 lookup table을 만들어야 한다. 그래서 메모리 공간을 더 사용하게 된다.
# 따라서 country에 중복되는 데이터가 많아서 몇몇의 다른 string만 있을 때에만 유용하게 사용할 수 있다.

drinks.memory_usage(deep=True) # 메모리 증가

데이터 정렬

df = pd.DataFrame({'ID': [100, 101, 102, 103], 'quality':['good', 'very good', 'good', 'excellent']})
df.sort_values('quality')

# 다음과 같은 순으로 정렬
from pandas.api.types import CategoricalDtype
quality_cat = CategoricalDtype(['good', 'very good', 'excellent'], ordered=True)
df['quality'] = df.quality.astype(quality_cat)

# 정렬 확인
df.sort_values('quality')
df.loc[df.quality > 'good', :]

22. scikit-learn과 pandas사용해서 kaggle submission 파일 만들기

본 링크에 따로 글을 만들었습니다.

[https://wordbe.tistory.com/entry/Tutorial-scikit-learn%EA%B3%BC-pandas%EC%82%AC%EC%9A%A9%ED%95%B4%EC%84%9C-kaggle-submission-%ED%8C%8C%EC%9D%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0]

23. Questions

랜덤으로 train, test 데이터 셋 구분

쉬운방법.

8:2로 나누어 봅시다.

train = ufo.sample(frac=0.8, random_state=13593)
test = ufo.loc[~ufo.index.isin(train.index), :]

24. Dummy variables

더미를 만들어봅시다.

즉, one-hot encoding 변수를 만들어봅시다.

Sex_male이라는 새로운 열을 만들어서, female이면 0, male이면 1이라고 했습니다.

train['Sex_male'] = train.Sex.map({'female': 0, 'male': 1})

사실 위에코드도 매우 직관적이고... 하드코딩까지의 느낌은 아니지만

get_dummies를 이용하면 그냥 한번에 만들 수 있습니다.

정말이지 머리를 굴리지 않는 느낌이군요.

pd.get_dummies(train.Sex)

>>
    female    male
0    0    1
1    1    0
2    1    0
3    1    0
4    0    1
...    ...    ...
886    0    1
887    1    0
888    1    0
889    0    1
890    0    1

prefix 매개변수로 원래 칼럼 이름앞에 접두어를 붙힐 수 있습니다.

pd.get_dummies(train.Embarked, prefix='Embarked')

embarked_dummies = pd.get_dummies(train.Embarked, prefix='Embarked').iloc[:, 1:] # drop the C column

train2 = pd.concat([train, embarked_dummies], axis=1)

이렇게 get_dummies를 뽑아, 기존의 테이블과 concat해도 되고,

pd.get_dummies(train, columns=['Sex', 'Embarked']) # 기존 Sex, Embarked 열을 삭제하고, 각각의 dummies에 칼럼명_을 prefix를 더해 이름지어 원본 오른쪽에 붙인다.

다음과 같이 활용하는 방법도 있습니다.

왜 필요한 기능인지는 잘 안와닿지만, 이런 부가적인기능도 있습니다.

pd.get_dummies(train, columns=['Sex', 'Embarked'], drop_first=True) # 각각 만든것 처음 열을 날린다.

25. Dates and Times

ufo.head()
>>

City    Colors Reported    Shape Reported    State    Time
0    Ithaca    NaN    TRIANGLE    NY    6/1/1930 22:00
1    Willingboro    NaN    OTHER    NJ    6/30/1930 20:00
2    Holyoke    NaN    OVAL    CO    2/15/1931 14:00
3    Abilene    NaN    DISK    KS    6/1/1931 13:00
4    New York Worlds Fair    NaN    LIGHT    NY    4/18/1933 19:00

다음과 같이 간단한 작업으로 시간을 골라낼 수 있습니다.

ufo.Time.str.slice(-5, -3).astype(int).head()

근데 판다스는 우리가 pd.to_datetime()을 이용하길 원합니다.

ufo['Time'] = pd.to_datetime(ufo.Time)

ufo.dtypes # day/month/year hour:miniutes
ufo.Time.dt.hour
ufo.Time.dt.weekday_name
ufo.Time.dt.week
ufo.Time.dt.dayofyear

여러 property가 있고, method 가 있어서 수학계산도 척척합니다.

ts = pd.to_datetime('1/1/1999') # Timestamp type
ufo.loc[ufo.Time >= ts, :]

(ufo.Time.max() - ufo.Time.min()).days #Timedelta type

마지막으로 연도별 ufo 출몰 수 그래프를 그려보겠습니다.

import matplotlib.pyplot as plt
ufo['Year'] = ufo.Time.dt.year
ufo.Year.value_counts().sort_index().plot()

[참고 - Data School https://www.youtube.com/watch?v=-NbY7E9hKxk&list=PL5-da3qGB5ICCsgW1MxlZ0Hq8LL5U3u9y&index=32]

728x90

댓글