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 = '날짜형식')
| 형식 | 설명 |
|---|
| %Y | 0을 채운 4자리 연도 |
| %y | 0을 채운 2자리 연도 |
| %m | 0을 채운 월 |
| %d | 0을 채운 일 |
| %H | 0을 채운 시간 |
| %M | 0을 채운 분 |
| %S | 0을 채운 초 |
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()
|
| Index | Date | Value | Window | 이동 평균 (mean) |
|---|
| 0 | 2023-01-01 | 10 | [10] | NaN |
| 1 | 2023-01-02 | 20 | [10, 20] | NaN |
| 2 | 2023-01-03 | 30 | [10, 20, 30] | (10+20+30)/3 = 20.0 |
| 3 | 2023-01-04 | 40 | [20, 30, 40] | (20+30+40)/3 = 30.0 |
| 4 | 2023-01-05 | 50 | [30, 40, 50] | (30+40+50)/3 = 40.0 |
| 5 | 2023-01-06 | 60 | [40, 50, 60] | (40+50+60)/3 = 50.0 |
| 6 | 2023-01-07 | 70 | [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: row나column기준으로 단순하게 이어 붙이기merge: 특정한 고유 키(unique id)값을 기준으로 병합
`pd.merge(left, right, on=’기준 컬럼’, how=’left’)
left, right : 병합할 두 DataFrameon: 병합의 기준이 되는 컬럼의 이름- 기준이 되는 데이터프레임은 삭제가 일어나지 않음!!!
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 : 하나의 데이터 프레임에 키값이 존재하는 경우 모두 병합
1
2
3
| pd.merge(df1_left, df2_right, on="이름", how="outer") # 한 쪽만 키값(이름)이 있어도 생성되고, 없는 값은 Nan값 처리
how = 'left' # left에 위치한 df1이 기준이 됨. 기준이 된 데이터프레임은 삭제가 일어나지 않음!!!
)
|
inner, outer 형식
inner: 두 데이터 프레임에 모두 키 값이 존재하는 경우 병합outer: 하나의 데이터 프레임에 키 값이 존재하는 경우 모두 병합
1
2
| # inner
pd.merge(df1_left, df2_right, on='이름', how='inner')
|
1
2
| # outer
pd.merge(df1_left, df2_right, on ="이름", how="outer")
|