Post

Pandas - 날짜 데이터 가공

Pandas - 날짜 데이터 가공

temperatures.csv 파일 사용

07. 날짜 데이터 가공

사전 준비

1
2
3
4
import pandas as pd

df = pd.read_csv("./data/temperatures.csv")
df.head()

가공할 날짜 정보가 어떤 형식인지 확인

  • 날짜 데이터는 날짜형으로 변경해야 여러가지 날짜 계산을 할 수 있다.
1
df.info() # 잘 불러왔나 확인 했으면 정보 확인

문자형을 날짜형으로 변경

  • pd.to_datetime(컬럼, format = '날짜형식')
형식설명
%Y0을 채운 4자리 연도
%y0을 채운 2자리 연도
%m0을 채운 월
%d0을 채운 일
%H0을 채운 시간
%M0을 채운 분
%S0을 채운 초
1
2
# 날짜형식으로 다룰 수 있게 변경
df["Date1"] = pd.to_datetime(df["Date"], format = '%Y-%m-%d')

날짜 데이터를 원하는 형식으로 변경

.dt.strftime(‘원하는형식’)

1
2
df["Date1"].dt.strftime("%Y-%m") # 숫자-숫자 표시
df["Date1"].dt.strftime("%Y년 %m월") # 숫자년 숫자월 표시
1
2
3
4
5
6
df['year'] = df["Date1"].dt.year # 년도
df['month'] = df['Date1'].dt.month # 월
df['day'] = df['Date1'].dt.day # 일

df['daypfweek'] = df['Date1'].dt.dayofweek # 요일(0 ~ 6) , 0이 월요일, 6은 일요일
df['dayname'] = df['Date1'].dt.day_name()

날짜 연산

  • day 연산 : pd.Timedelta(day = 숫자)
  • month 연산 : DateOffset(months = 숫자)
  • year 연산 : DateOffset(years = 숫자)

day 계산

1
2
# 하루 뒤 날짜 계산
df['plus_day1'] = df['Date1'] + pd.Timedelta(days=1)
1
2
# 7일 전 날짜 계산
df['minus day7'] = df['Date1'] + pd.Timedelta(days = -7) 

months, years 계산

  • from pandas.tseries.offsets import DateOffset 를 해줘야함.
1
2
3
# 월 변화
df['plus_month1'] = df['Date1'] + DateOffset(months = 1)
df['minus month3'] = df['Date1'] + DateOffset(months = -3)
1
2
3
# 년 변화
df['plus year1'] = df['Date1'] + DateOffset(years = 1)
df['plus year1'] = df['Date1'] + DateOffset(years = -1)

날짜 구간 데이터 만들기

pd.date_range(start = 시작일자, end = 종료일자, periods = 기간수, freq = 주기)

형식설명
D일별
W주별
M월별 말일
MS월별 시작일
A연도별 말일
AS연도별 시작일

오늘부터 30일 뒤의 날짜

1
pd.date_range(start="2025-01-14", periods = 30, freq = "D")

구간동안의 월 마지막 날 출력

1
pd.date_range(start="2025-01-01", end="2025-06-30", freq = "M")

구간동안의 월 첫 날 출력

1
pd.date_range(start="2025-01-01", end="2025-06-30", freq = "MS")

구간동안의 년 첫 마지막 날 출력

1
pd.date_range(start = "2025-01-01", end = "2036-12-15", freq = 'A')

구간동안의 년 첫 날 출력

1
pd.date_range(start="2025-01-01", end="2035-12-15", freq='AS')

기간 이동 계산

rolling

  • 데이터의 지정된 크기의 윈도우(슬라이딩 창)를 이동시키며 계산을 수행.
  • 주로 시계열 데이터에서 시간 구간별 통계량을 계산할 때 사용됨.
  • 예를 들어, 3일 이동 평균, 30일 이동 합계 등을 구할 때 사용.
1
2
# 3일 이동 평균을 구한다고 가정. 
df['rolling_avg'] = df['value'].rolling(window=3).mean()
IndexDateValueWindow이동 평균 (mean)
02023-01-0110[10]NaN
12023-01-0220[10, 20]NaN
22023-01-0330[10, 20, 30](10+20+30)/3 = 20.0
32023-01-0440[20, 30, 40](20+30+40)/3 = 30.0
42023-01-0550[30, 40, 50](30+40+50)/3 = 40.0
52023-01-0660[40, 50, 60](40+50+60)/3 = 50.0
62023-01-0770[50, 60, 70](50+60+70)/3 = 60.0

행 이동

각 행의 Temp 데이터를 한 칸씩 아래로 이동

1
2
3
4
df['Time Shift1'] = df['Temp'].shift(1)

# 이동한 결과 값을 빼서 어제와의 온도 변화 % 구하기
df['pct change'] = (df['Time Shift1'] - df["Temp"]) / df['Temp']

08. apply, map, 문자열

titanic_train.csv 사용

apply

  • 사용자 정의 함수를 데이터에 적용할 때 사용
  • 레코드(행)단위로 사용자 정의 함수 적용
    • apply에 들어가는 함수는 반드시 리턴이 있어야 한다.

두 개의 다른 컬럼 값 비교

  • Pclass가 1이고, SibSp가 1이면 1, 아니면 0
1
2
3
4
5
6
7
def pclass_sibsp(row): # 행 단위 계산
  if row["Pclass"] == 1 and row["SibSp"] == 1:
    return 1
  else:
    return 0

  df1.["Pclass_sibsp_filter"] = df1.apply(pclass_sibsp, axis=1) # 열 방향으로 함수 적용

-lamda 함수와 삼항연산자를 사용해서 만들기

1
2
3
df1["pclass_sibsp_lambda"] = df1.apply(
  lambda row : 1 if row["Pclass"] == 1 and row["SibSp"] == 1 else 0, axis = 1
)

한 개의 컬럼

  • 성인인지 아닌지
1
2
3
4
5
6
7
8
9
10
11
import numpy as np # nan값 리턴 때문에

def adult(age):
  if age >= 19:
    return 1
  elif age < 19:
    return 0
  else: 
    return np.nan

df1["adult_yn"] = df1["Age"].apply(adult) # 시리즈 하나에서만 비교기 때문에 axis = 0
  • lambda 함수와 삼항연산자를 사용해서 만들기
1
df1["adult_yn"] = df1["Age"].apply(lambda row : 1 if age >= 19 else 0 if age < 19 else np.nan)

map

  • apply : 기능 실행 / map : mapping(맞춰준다, 1대1 변환 느낌)
  • 값을 특정 값으로 치환할 때 사용
  • logic적인 부분이 들어가면 map을 쓰지 못 함

map -> dict

1
2
3
4
5
gender_map = {
  "male" : "남자",
  "female" : "여자"
}
df1["Sex_kr"] = df1["Sex"].map(gender_map)

문자열 시리즈 다루기

  • 문자열 형태의 시리즈에서만 가능!!!
메소드설명 
 .str.contains(문자열)문자열을 포함하고 있는지 유무
 .str.replace(기존문자열, 대치문자열)문자열 대치
 .str.split(문자열, expand=True/False, n=개수)특정 문자열을 기준으로 쪼개기
 .str.lower()소문자로 바꾸기
 .str.upper()대문자로 바꾸기

이름에 ‘Miss’가 들어간 사람만 찾기

1
2
# 문자열을 담고 있는 series 반환
df2["Name"].str.contains("Miss")
  • mask 활용
    1
    2
    
    miss_mask = df2["Name"].str.contains("Miss")
    df2.loc[miss_mask]
    

    시리즈 값의 “,”를 바꾸기

    1
    
    df2["Name"] = df2["Name"].str.replace(",", "⭐️")
    

09. 데이터 결합

concat

row 기준 합치기

  • aixs = 0
  • 행 데이터의 생성 방향, 아래쪽
  • 열 인덱스 기준으로 결합
1
2
df1_concat = pd.concat([df1, df1_copy], axis = 0)
df1_concat.reset_index(drop=True) # 기존에 사용하던 인덱스를 drop하고 인덱스 리셋

column 기준 합치기

  • axis = 1
  • 열 데이터의 생성 방향, 옆쪽
  • 행 인덱스 기준으로 결합
1
pd.concat([df1, df2], axis = 1) # 열방향(옆으로), 행 인덱스가 같은 것 끼리

merge

  • concat: rowcolumn기준으로 단순하게 이어 붙이기
  • merge: 특정한 고유 키(unique id)값을 기준으로 병합

`pd.merge(left, right, on=’기준 컬럼’, how=’left’)

  • left, right : 병합할 두 DataFrame
  • on: 병합의 기준이 되는 컬럼의 이름
    • 기준이 되는 데이터프레임은 삭제가 일어나지 않음!!!
  • how: left, right, inner, outer 4가지의 병합방식 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
pd.merge(
  df1,
  df2_right,
  on = '이름',
  how = 'left' # left에 위치한 df1이 기준이 된다. 기준이 된 데이터프레임은 데이터의 삭제가 일어나지 않음..!!!!!
)

pd.merge(
    df1,
    df2_right,
    on = "이름",
    how = 'right' # 기준이 오른쪽이 됨
) 

inner

  • inner : 두 데이터 프레임에 모두 키값이 존재하는 경우 병합
1
pd.merge(df1_left, df2_right, on='이름', how="inner") # 왼,오 데이터프레임에 모두 키값(이름)이 존재하는 것만 병합!

outer

  • outer : 하나의 데이터 프레임에 키값이 존재하는 경우 모두 병합
    • 없는 값은 NaN값으로 대입
1
2
3
pd.merge(df1_left, df2_right, on="이름", how="outer") # 한 쪽만 키값(이름)이 있어도 생성되고, 없는 값은 Nan값 처리
  how = 'left' # left에 위치한 df1이 기준이 됨. 기준이 된 데이터프레임은 삭제가 일어나지 않음!!!
)

inner, outer 형식

  • inner: 두 데이터 프레임에 모두 키 값이 존재하는 경우 병합
  • outer: 하나의 데이터 프레임에 키 값이 존재하는 경우 모두 병합
    • 없는 값은 NaN값으로 대입
1
2
# inner
pd.merge(df1_left, df2_right, on='이름', how='inner')
1
2
# outer
pd.merge(df1_left, df2_right, on ="이름", how="outer")
This post is licensed under CC BY 4.0 by the author.