[빅분기 실기] 작업형 1유형 : 판다스 주요 문법 2
이전 내용
[빅분기 실기] 작업형 1유형 : 판다스 주요 문법 1
이전 내용 [빅분기 실기] 빅분기 실기 접수이전 내용 [빅분기 필기] 응시자격 심사 서류 제출이전 내용 [빅분기 필기] 2차 도전! (요약 자료 다운로드)이전 내용 [빅분기 필기] (분노와 슬픔의) 시
puppy-foot-it.tistory.com
그룹핑2
- transform(): 같은 그룹 내에서 특정 기준에 맞는 연산 수행
먼저, 아래와 같은 데이터프레임을 만든다.
# transform
import pandas as pd
import numpy as np
df = pd.DataFrame({
'브랜드': ['뉴발란스', '나이키', '아디다스', '나이키', '아디다스', '뉴발란스', '아디다스', '뉴발란스' ,'나이키'],
'가격': [1000, np.nan, 1500, np.nan, 1200, np.nan, 1800, 800, 1300]
})
df
groupby를 통해 브랜드 별로 묶고, transform('mean')을 사용하여 각 행마다 해당 그룹의 평균값을 계산해 본다.
price = df.groupby('브랜드')['가격'].transform('mean')
price
이때 평균은 결측값을 제외한 값으로 평균을 계산하고 원본 데이터와 같은 길이의 시리즈로 나타낸다.
fillna()를 사용해 결측값만 위에서 계산한 평균 그룹으로 채운다.
df['가격'] = df['가격'].fillna(price)
df
- 두 개의 조건을 기준으로 평균 구하기
기존 데이터프레임에 '성별'을 추가하여 브랜드와 성별을 기준으로 각 그룹의 평균을 구하고 결측값에 적용해 본다.
import pandas as pd
import numpy as np
df = pd.DataFrame({
'브랜드': ['뉴발란스', '나이키', '아디다스', '나이키', '아디다스', '뉴발란스', '아디다스', '뉴발란스' ,'나이키', '나이키'],
'성별': ['남성', '여성', '여성', '남성', '남성', '여성', '여성', '여성', '남성', '여성'],
'가격': [1000, np.nan, 1500, np.nan, 1200, np.nan, 1800, 800, 1300, 900]
})
df
각 브랜드와 성별 평균을 transform('mean')으로 계산하여 각 그룹의 평균값을 구한다.
price = df.groupby(['성별', '브랜드'])['가격'].transform('mean')
price
fillna()를 사용하여 결측값에 해당 그룹의 평균값을 채운다.
df['가격'] = df['가격'].fillna(price)
df
- unstack(): groupby 이후 다중 인덱스가 설정된 상태에서 특정 인덱스를 컬럼으로 변환
grouped = df.groupby(['브랜드', '성별'])['가격'].mean()
grouped
브랜드와 성별을 기준으로 groupby() 수행 시 다중인덱스가 적용되는데, 이때 unstack()을 사용하면 특정 인덱스를 컬럼으로 변환할 수 있다.
grouped.unstack()
▶ 성별이 남성과 여성 컬럼으로 변환된다.
level을 설정하면 변환 방식을 바꿀 수 있다. (기본값은 -1)
grouped.unstack(level=0)
unstack()을 두 번 적용하면, 두 개의 인덱스를 모두 컬럼으로 이동시킨다.
grouped.unstack().unstack()
시계열 데이터
판다스는 시계열 (날짜, 시간 등) 데이터를 처리할 수 있는 datetime을 제공하고 있다.
파이썬은 데이터를 불러올 때 날짜와 시간을 자동으로 인식하지 못하며, 문자열 데이터로 인식한다. (자료형은 보통 object)
따라서, 시계열 데이터를 다루기 위해 자료형을 파싱하는데 (object → datetime), 판다스의 to_datetime()을 사용해 데이터를 변경한다. 대부분의 날짜와 시간 형태는 판다스가 자동으로 인식해 변경하며, 만약 인식을 못했을 때는 format 설정을 별도로 해주면 된다.
https://pandas.pydata.org/docs/reference/api/pandas.to_datetime.html
pandas.to_datetime — pandas 2.2.3 documentation
Control timezone-related parsing, localization and conversion. Warning In a future version of pandas, parsing datetimes with mixed time zones will raise an error unless utc=True. Please specify utc=True to opt in to the new behaviour and silence this warni
pandas.pydata.org
다양한 형태의 시계열 데이터를 만들어 본 후 테스트해 본다.
# 시계열 데이터
import pandas as pd
df = pd.DataFrame({
'type1': ['2025-05-20'],
'type2': ['2025:05:20'],
'type3': ['2025/05/20'],
'type4': ['20/05/2025'],
'type5': ['20-May-2025'],
'type6': ['2025-05-20 15:43:30'],
'type7': ['2025-05-20 15-43-30'],
'type8': ['2025-05-20 03:43:30 PM'],
'type9': ['20/05/2025 03:43:30 PM'],
'type10': ['20 May 2025 15:43:30']
})
df
- 자료형 보기
df.info()
◆ to_datetime()
- pd.to_datetime() 으로 자료형 변경하기
# pd.to_datetime datetime으로 자료형 변경
df['type1'] = pd.to_datetime(df['type1'])
# df['type2'] = pd.to_datetime(df['type2']) # 에러 발생: ['2025:05:20']
df['type3'] = pd.to_datetime(df['type3'])
df['type4'] = pd.to_datetime(df['type4'])
df['type5'] = pd.to_datetime(df['type5'])
df['type6'] = pd.to_datetime(df['type6'])
# df['type7'] = pd.to_datetime(df['type7']) # 에러 발생: ['2025-05-20 15-43-30']
df['type8'] = pd.to_datetime(df['type8'])
df['type9'] = pd.to_datetime(df['type9'])
df['type10'] = pd.to_datetime(df['type10'])
df
▶ type2와 type7의 경우, 에러가 발생한다.
- type2: 일반적으로 콜론은 시간을 나타날 때 사용하므로, 날짜 데이터에 사용 못함
- type7: 시간을 나타낼 때 '-' 사용하지 않으면 판다스가 자동으로 인식하지 못함.
만약, 해당 형식을 꼭 사용해야 한다면 format을 설정해야 한다.
df['type2'] = pd.to_datetime(df['type2'], format='%Y:%m:%d')
df['type7'] = pd.to_datetime(df['type7'], format='%Y-%m-%d %H-%M-%S')
형 변환을 한 후, 다시 데이터프레임 정보를 출력해 보면
df.info()
◆ dt
- 날짜와 시간 데이터 분할 (dt 속성)
판다스의 dt를 활용해 datetime 자료형을 연도, 월, 일, 시간, 분, 초, 요일 등을 분리할 수 있다.
먼저 데이터프레임을 전치(T) 시킨 다음, 각 데이터에서 시간 단위를 추출해 컬럼으로 저장해 본다.
new_df = df.T
new_df.columns = ['date'] # 컬럼 이름 지정
new_df
new_df['year'] = new_df['date'].dt.year
new_df['month'] = new_df['date'].dt.month
new_df['day'] = new_df['date'].dt.day
new_df['hour'] = new_df['date'].dt.hour
new_df['min'] = new_df['date'].dt.minute
new_df['sec'] = new_df['date'].dt.second
new_df['dayofweek'] = new_df['date'].dt.dayofweek
new_df
▶ 요일(dayofweek)의 경우, 0:월요일 ~ 6:일요일의 값을 나타낸다.
◆ dt.to_period()
- 특정 구간(period)
datetime의 경우 특정 시점을 나타내며, period는 특정 시간 범위나 구간을 나타낸다.
만약 특정 시점을 특정 구간으로 변환하려면 dt.to_period('빈도') 를 적용해 주면 된다.
빈도(Frequency) | 설명 | 예시 날짜 | 결과 |
Y | 연도 | 2025-05-20 | 2025 |
Q | 분기 | 2025-05-20 | 2025Q2 |
M | 월 | 2025-05-20 | 2025-05 |
W | 주 | 2025-05-20 | 2025-04-28 (주 시작일) |
D | 일 | 2025-05-20 | 2025-05-20 |
h | 시간 | 2025-05-20 15:43 | 2025-05-20 15 |
min | 분 | 2025-05-20 15:43:30 | 2025-05-20 15:43 |
s | 초 | 2025-05-20 15:43:30 | 2025-05-20 15:43:30 |
B | 영업일(기간) | 2025-05-20 | 2025-05-20 (영업일) |
print(df['type1'].dt.to_period('Y')) # 연도
print(df['type1'].dt.to_period('Q')) # 분기
print(df['type1'].dt.to_period('M')) # 월
print(df['type1'].dt.to_period('W')) # 주
print(df['type1'].dt.to_period('D')) # 일
print(df['type1'].dt.to_period('h')) # 시간
print(df['type1'].dt.to_period('min')) # 분
print(df['type1'].dt.to_period('s')) # 초
★ Y-DEC, Q-DEC, W-SUN?
Y-DEC, Q-DEC, W-SUN Pandas의 Period 객체에서 사용되는 빈도(Frequency) 문자열이다.
빈도(Frequency) | 설명 | 예시 |
Y-DEC | 연말 기준의 연도(Annual frequency, December). 예, 2025-12-31은 2025년. |
2025-05-20 → 2025 |
Q-DEC | 연말 기준의 분기(Quarterly frequency, December). 예, 2025-11-15는 2025년 4분기. |
2025-05-20 → 2025Q2 |
W-SUN | 주 기준으로, 주의 마지막 날이 일요일(Sunday)임을 지정 예, 2025-05-20은 포함된 주의 일요일. |
2025-05-20 → 2025-05-19/2025-05-25 |
◆ Timedleta
Timedleta는 두 시점 사이의 차이를 나타내며, 날짜와 시간을 더하거나 뺄 수 있다. datetime 자료형의 경우 연산을 하게 되면 그 결괏값은 Timedelta 자료형이 된다.
date 컬럼의 날짜로부터 50일 이후의 날짜를 계산해 본다.
d_day = pd.Timedelta(days=50)
new_df['50day'] = new_df['date'] + d_day
new_df
파라미터로 줄 수 있는 값
- weeks: 주
- hours: 시간
- minutes: 분
- seconds: 초
- milliseconds, microseconds, nanoseconds
년(year), 월(month)을 줄 수 없다.
cannot construct a Timedelta from the passed arguments,
allowed keywords are
[weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds]
또한, 한 번에 여러 매개변수를 줄 수 있다.
some_day = pd.Timedelta(weeks=3, days=3, hours=3, minutes=3, seconds=3)
new_df['some_day'] = new_df['date'] + some_day
new_df
- 두 시점의 차이
diff = new_df['50day'] - new_df['some_day']
diff
★ dt.total_seconds():
전체 시간을 초 단위로 변경
Timedelta 자료형에 dt.total_seconds()를 활용하면 전체 시간을 초 단위로 변경할 수 있다.
print(diff.dt.total_seconds())
print(diff.dt.total_seconds()/60) # 분
print(diff.dt.total_seconds()/60/60) # 시간
print(diff.dt.total_seconds()/60/60/24) # 일
- 시간 반올림
시간을 반올림할 때는 round() 를 사용하면 된다.
print(round(diff.dt.total_seconds()))
print(round(diff.dt.total_seconds()/60)) # 분
print(round(diff.dt.total_seconds()/60/60)) # 시간
print(round(diff.dt.total_seconds()/60/60/24)) # 일
다음 내용
[빅분기 실기] 작업형 1유형 : 판다스 주요 문법 3
이전 내용 [빅분기 실기] 작업형 1유형 : 판다스 주요 문법 2이전 내용 [빅분기 실기] 작업형 1유형 : 판다스 주요 문법 1이전 내용 [빅분기 실기] 빅분기 실기 접수이전 내용 [빅분기 필기] 응시자
puppy-foot-it.tistory.com