본문 바로가기
pandas

데이터 전처리, 추가, 삭제, 변환

by 자동매매 2023. 12. 12.

참조 :

한 권으로 끝내는 <판다스 노트>

https://e-koreatech.step.or.kr/

 

from IPython.display import Image
import numpy as np
import pandas as pd
import seaborn as sns
import warnings

# warning 무시
warnings.filterwarnings('ignore')

# e notation 표현 방식 변경
pd.options.display.float_format = '{:.2f}'.format

# 모든 컬럼 표시
pd.set_option('display.max_columns', None)

 

df = sns.load_dataset('titanic')
df1 = df.copy()

df1.head()

 

1. 새로운 컬럼 추가

insert(컬럼인덱스, 컬럼명, 값)

df1.insert(5, 'RICH', df1['fare'] > 100)

 

2. 삭제

1) 행 (row) 삭제 - index를 지정하여 삭제

df2 = df1.drop(1)
df2
df1.drop(np.arange(10))
df1.drop([1, 3, 5, 7, 9])

 

2) 열 (column) 삭제 - 반드시 axis=1 옵션을 지정

df2 = df1.drop('class', axis=1).head()
df2
df2 = df1.drop(['who', 'deck', 'alive'], axis=1) # 다수의 컬럼(column) 삭제
df2

 

3) 삭제된 내용을 바로 적용하려면 inplace=True를 지정

df1.drop(['who', 'deck', 'alive'], axis=1, inplace=True)
df1

 

3. 컬럼간 연산

df1['family'] = df1['sibsp'] + df1['parch']
df1['gender'] = df1['who'] + '-' + df1['sex'] # 문자열 이어붙히기
df1['round'] = round(df1['fare'] / df1['age'], 2)

 

 

연산시 1개의 컬럼이라도 NaN 값을 포함하고 있다면 결과는 NaN 이 됩니다.

df1.loc[df1['age'].isnull(), 'deck':].head()
 
 

4. category 타입

1)  category로 변경 : 사용하는 메모리 감소

 

df1['who'].astype('category').head()
0      man
1    woman
2    woman
3    woman
4      man
Name: who, dtype: category
Categories (3, object): ['child', 'man', 'woman']

 

df1['who'] = df1['who'].astype('category')

 

2) 카테고리 출력

df1['who'].cat.categories
Index(['child', 'man', 'woman'], dtype='object')

 

 

3) 카테고리 이름 변경

df1['who'].cat.categories = ['아이', '남자', '여자']
df1['who'].value_counts()
남자    537
여자    271
아이     83
Name: who, dtype: int64

 

 

5. datetime - 날짜, 시간

도큐먼트

  • pandas.Series.dt.year: 연도
  • pandas.Series.dt.quarter: 분기
  • pandas.Series.dt.month: 월
  • pandas.Series.dt.day: 일
  • pandas.Series.dt.hour: 시
  • pandas.Series.dt.minute: 분
  • pandas.Series.dt.second: 초
  • pandas.Series.dt.microsecond: micro 초
  • pandas.Series.dt.nanosecond: nano 초
  • pandas.Series.dt.week: 주
  • pandas.Series.dt.weekofyear: 연중 몇 째주
  • pandas.Series.dt.dayofweek: 요일
  • pandas.Series.dt.weekday: 요일 (dayofweek과 동일)
  • pandas.Series.dt.dayofyear: 연중 몇 번째 날

 1) to_datetime

pandas.to_datetime(param,   format)

param: 변환할 열명

format: 날짜 변환 형식 문자열

 

# 실습용 데이터셋 다운로드
!pip install opendata-kr -q

from opendata import dataset

dataset.download('서울시자전거')

 

# 데이터셋 로드
df2 = pd.read_csv('data/seoul_bicycle.csv')
df2.head()

 

df2.info()

 

RangeIndex: 327231 entries, 0 to 327230
Data columns (total 11 columns):
 #   Column  Non-Null Count   Dtype  
---  ------  --------------   -----  
 0   대여일자    327231 non-null  object 
 1   대여소번호   327231 non-null  int64  
 2   대여소명    327231 non-null  object 
 3   대여구분코드  327231 non-null  object 
 4   성별      272841 non-null  object 
 5   연령대코드   327231 non-null  object 
 6   이용건수    327231 non-null  int64  
 7   운동량     327231 non-null  object 
 8   탄소량     327231 non-null  object 
 9   이동거리    327231 non-null  float64
 10  이용시간    327231 non-null  int64  
dtypes: float64(1), int64(3), object(7)
memory usage: 27.5+ MB

 


대여일자 컬럼은 object로 인식, datetime타입으로 변경해야 .dt 접근자를 사용할 수 있습니다.

pd.to_datetime(): datetime type으로 변환합니다.

df2['대여일자'] = pd.to_datetime(df2['대여일자'])
# df2['대여일자'] = pd.to_datetime(df2['대여일자'], format="%Y-%m-%d")

 

df2.info()
RangeIndex: 327231 entries, 0 to 327230
Data columns (total 11 columns):
 #   Column  Non-Null Count   Dtype         
---  ------  --------------   -----         
 0   대여일자    327231 non-null  datetime64[ns]
 1   대여소번호   327231 non-null  int64         
 2   대여소명    327231 non-null  object        
 3   대여구분코드  327231 non-null  object        
 4   성별      272841 non-null  object        
 5   연령대코드   327231 non-null  object        
 6   이용건수    327231 non-null  int64         
 7   운동량     327231 non-null  object        
 8   탄소량     327231 non-null  object        
 9   이동거리    327231 non-null  float64       
 10  이용시간    327231 non-null  int64         
dtypes: datetime64[ns](1), float64(1), int64(3), object(6)
memory usage: 27.5+ MB

 

df2['대여일자'].dt.year
df2['대여일자'].dt.month
df2['대여일자'].dt.day
df2['대여일자'].dt.dayofweek

 

df3 = pd.DataFrame([], index=df1.index)
df3["datetime"] = df2["대여일자"]
df3["week"] = df3["datetime"].dt.week
df3["weekday"] = df3["datetime"].dt.weekday
df3["dayofyear"] = df3["datetime"].dt.dayofyear

df3
datetime	week	weekday	dayofyear
0	2020-01-20	4	0	20
1	2020-01-20	4	0	20
2	2020-01-20	4	0	20
3	2020-01-20	4	0	20
4	2020-01-20	4	0	20
...	...	...	...	...
886	2020-01-20	4	0	20
887	2020-01-20	4	0	20
888	2020-01-20	4	0	20
889	2020-01-20	4	0	20
890	2020-01-20	4	0	20
891 rows × 4 columns

 

 

6. pd.cut() - 구간 나누기(binning)

연속된 수치(continuous values)를 구간으로 나누어 카테고리화 할 때 사용합니다.

 

1) right=False로 지정시 우측 범위를 포함하지 않습니다.

bins = [0, 6000, 100000, df2['이동거리'].max()]
pd.cut(df2['이동거리'], bins, right=False)

 

0                   [0.0, 6000.0)
1                   [0.0, 6000.0)
2              [6000.0, 100000.0)
3                   [0.0, 6000.0)
4         [100000.0, 56709052.94)
                   ...           
327226         [6000.0, 100000.0)
327227              [0.0, 6000.0)
327228              [0.0, 6000.0)
327229              [0.0, 6000.0)
327230    [100000.0, 56709052.94)
Name: 이동거리, Length: 327231, dtype: category
Categories (3, interval[float64, left]): [[0.0, 6000.0) < [6000.0, 100000.0) < [100000.0, 56709052.94)]

 

2) labels를 지정해 줄 수 있으며, 지정한 bins의 개수보다 1 개가 적어야 합니다.

labels = ['적음', '보통', '많음']
pd.cut(df2['이동거리'], bins, labels=labels, right=False)
0         적음
1         적음
2         보통
3         적음
4         많음
          ..
327226    보통
327227    적음
327228    적음
327229    적음
327230    많음
Name: 이동거리, Length: 327231, dtype: category
Categories (3, object): ['적음' < '보통' < '많음']

 

3) pd.cut()을 활용하여 쉽게 그룹을 나눌 수 있습니다.

bins 옵션에 나누고자 하는 구간의 개수를 설정합니다.

df2['이동거리_cut'] = pd.cut(df2['이동거리'], bins=3)
df2['이동거리_cut'].value_counts()
(-56709.053, 18903017.647]      327216
(18903017.647, 37806035.293]        12
(37806035.293, 56709052.94]          3
Name: 이동거리_cut, dtype: int64

 

4. pd.qcut() - 동일한 갯수를 갖도록 구간 분할

pd.cut()과 유사하지만, quantity 즉 데이터의 분포를 최대한 비슷하게 유지하는 구간을 분할 합니다.

df2['이동거리_qcut'] = pd.qcut(df2['이동거리'], q=3)
df2['이동거리_qcut'].value_counts()
(-0.001, 9030.0]          109095
(60470.0, 56709052.94]    109072
(9030.0, 60470.0]         109064
Name: 이동거리_qcut, dtype: int64

 

구간도 예쁘게 분할(균등하게 분할)이 된 것 처럼 보입니다. 하지만, 간격은 일정하지 않습니다.

qcut 또한 임의 범위를 조정할 수 있습니다.

qcut_bins = [0, 0.2, 0.8, 1]
pd.qcut(df2['이동거리'], qcut_bins)
0                (-0.001, 3570.0]
1                (-0.001, 3570.0]
2              (3570.0, 125530.0]
3                (-0.001, 3570.0]
4         (125530.0, 56709052.94]
                   ...           
327226         (3570.0, 125530.0]
327227           (-0.001, 3570.0]
327228           (-0.001, 3570.0]
327229           (-0.001, 3570.0]
327230    (125530.0, 56709052.94]
Name: 이동거리, Length: 327231, dtype: category
Categories (3, interval[float64, right]): [(-0.001, 3570.0] < (3570.0, 125530.0] < (125530.0, 56709052.94]]

 

 

qcut_labels = ['적음', '보통', '많음']
pd.qcut(df2['이동거리'], qcut_bins, labels=qcut_labels).value_counts()
보통    196307
적음     65482
많음     65442
Name: 이동거리, dtype: int64
 

 

'pandas' 카테고리의 다른 글

연결(Concat)과 병합(Merge)  (0) 2023.12.12
Groupby와 Pivot table  (0) 2023.12.12
복사와 결측치  (0) 2023.12.12
통계  (0) 2023.12.11
조회, 정렬, 조건필터  (0) 2023.12.11

댓글