Reference
- DataManim (https://www.datamanim.com/dataset/99_pandas/pandasMain.html#)
- <파이썬 한권으로 끝내기>, 데싸라면▪빨간색 물고기▪자투리코드, 시대고시기획 시대교육
DataSet
주가 데이터 : https://raw.githubusercontent.com/guipsamora/pandas_exercises/master/06_Stats/Wind_Stats/wind.data
DataUrl = ‘https://raw.githubusercontent.com/Datamanim/pandas/main/timeTest.csv%E2%80%99
Question
✔ 데이터를 로드하고 각 열의 데이터 타입을 파악하라
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/Datamanim/pandas/main/timeTest.csv')
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6574 entries, 0 to 6573
Data columns (total 13 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Yr_Mo_Dy 6574 non-null object
1 RPT 6568 non-null float64
2 VAL 6571 non-null float64
3 ROS 6572 non-null float64
4 KIL 6569 non-null float64
5 SHA 6572 non-null float64
6 BIR 6574 non-null float64
7 DUB 6571 non-null float64
8 CLA 6572 non-null float64
9 MUL 6571 non-null float64
10 CLO 6573 non-null float64
11 BEL 6574 non-null float64
12 MAL 6570 non-null float64
dtypes: float64(12), object(1)
memory usage: 667.8+ KB
✔ Yr_Mo_Dy을 판다스에서 인식할 수 있는 datetime64타입으로 변경하라
df.Yr_Mo_Dy = pd.to_datetime(df.Yr_Mo_Dy)
Ans = df.Yr_Mo_Dy
Ans
0 2061-01-01
1 2061-01-02
2 2061-01-03
3 2061-01-04
4 2061-01-05
...
6569 1978-12-27
6570 1978-12-28
6571 1978-12-29
6572 1978-12-30
6573 1978-12-31
Name: Yr_Mo_Dy, Length: 6574, dtype: datetime64[ns]
+ pd.to_datetime() : 날짜/시간 형식의 데이터를 pandas의 datetime 형식으로 변환하는데 사용
✔ Yr_Mo_Dy에 존재하는 년도의 유일값을 모두 출력하라
Ans = df.Yr_Mo_Dy.dt.year.unique()
Ans
array([2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 1971,
1972, 1973, 1974, 1975, 1976, 1977, 1978])
✔ Yr_Mo_Dy에 년도가 2061년 이상의 경우에는 모두 잘못된 데이터이다. 해당경우의 값은 100을 빼서 새롭게 날짜를 Yr_Mo_Dy 컬럼에 정의하라
def fix_century(x) :
import datetime
if x.year >= 2061 :
year = x.year - 100
else :
year = x.year
return pd.to_datetime(datetime.date(year, x.month, x.day))
# datetime.date(년, 월, 일)
df['Yr_Mo_Dy'] = df['Yr_Mo_Dy'].apply(fix_century)
df.head()
Yr_Mo_Dy | RPT | VAL | ROS | KIL | SHA | BIR | DUB | CLA | MUL | CLO | BEL | MAL | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1961-01-01 | 15.04 | 14.96 | 13.17 | 9.29 | NaN | 9.87 | 13.67 | 10.25 | 10.83 | 12.58 | 18.50 | 15.04 |
1 | 1961-01-02 | 14.71 | NaN | 10.83 | 6.50 | 12.62 | 7.67 | 11.50 | 10.04 | 9.79 | 9.67 | 17.54 | 13.83 |
2 | 1961-01-03 | 18.50 | 16.88 | 12.33 | 10.13 | 11.17 | 6.17 | 11.25 | NaN | 8.50 | 7.67 | 12.75 | 12.71 |
3 | 1961-01-04 | 10.58 | 6.63 | 11.75 | 4.58 | 4.54 | 2.88 | 8.63 | 1.79 | 5.83 | 5.88 | 5.46 | 10.88 |
4 | 1961-01-05 | 13.33 | 13.25 | 11.42 | 6.17 | 10.71 | 8.21 | 11.92 | 6.54 | 10.92 | 10.34 | 12.92 | 11.83 |
✔ 년도별 각 컬럼의 평균값을 구하여라
Ans = df.groupby(df.Yr_Mo_Dy.dt.year).mean()
Ans.head()
Yr_Mo_Dy | RPT | VAL | ROS | KIL | SHA | BIR | DUB | CLA | MUL | CLO | BEL | MAL | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Yr_Mo_Dy | |||||||||||||
1961 | 1961-07-02 00:00:00 | 12.299583 | 10.351796 | 11.362369 | 6.958227 | 10.881763 | 7.729726 | 9.733923 | 8.858788 | 8.647652 | 9.835577 | 13.502795 | 13.680773 |
1962 | 1962-07-02 00:00:00 | 12.246923 | 10.110438 | 11.732712 | 6.960440 | 10.657918 | 7.393068 | 11.020712 | 8.793753 | 8.316822 | 9.676247 | 12.930685 | 14.323956 |
1963 | 1963-07-02 00:00:00 | 12.813452 | 10.836986 | 12.541151 | 7.330055 | 11.724110 | 8.434712 | 11.075699 | 10.336548 | 8.903589 | 10.224438 | 13.638877 | 14.999014 |
1964 | 1964-07-01 12:00:00 | 12.363661 | 10.920164 | 12.104372 | 6.787787 | 11.454481 | 7.570874 | 10.259153 | 9.467350 | 7.789016 | 10.207951 | 13.740546 | 14.910301 |
1965 | 1965-07-02 00:00:00 | 12.451370 | 11.075534 | 11.848767 | 6.858466 | 11.024795 | 7.478110 | 10.618712 | 8.879918 | 7.907425 | 9.918082 | 12.964247 | 15.591644 |
✔ weekday컬럼을 만들고 요일별로 매핑하라 ( 월요일: 0 ~ 일요일 :6)
df['weekday'] = df.Yr_Mo_Dy.dt.weekday
Ans = df['weekday'].to_frame()
Ans
weekday | |
---|---|
0 | 6 |
1 | 0 |
2 | 1 |
3 | 2 |
4 | 3 |
... | ... |
6569 | 2 |
6570 | 3 |
6571 | 4 |
6572 | 5 |
6573 | 6 |
6574 rows × 1 columns
✔ weekday컬럼을 기준으로 주말이면 1 평일이면 0의 값을 가지는 WeekCheck 컬럼을 만들어라
df['WeekCheck'] = df['weekday'].map(lambda x :
1 if x in [5,6]
else 0)
# 월요일(Monday): 0
# 화요일(Tuesday): 1
# 수요일(Wednesday): 2
# 목요일(Thursday): 3
# 금요일(Friday): 4
# 토요일(Saturday): 5
# 일요일(Sunday): 6
Ans = df['WeekCheck'].to_frame()
Ans
WeekCheck | |
---|---|
0 | 1 |
1 | 0 |
2 | 0 |
3 | 0 |
4 | 0 |
... | ... |
6569 | 0 |
6570 | 0 |
6571 | 0 |
6572 | 1 |
6573 | 1 |
6574 rows × 1 columns
✔ 년도, 일자 상관없이 모든 컬럼의 각 달의 평균을 구하여라
Ans = df.groupby(df.Yr_Mo_Dy.dt.month).mean()
Ans.head()
Yr_Mo_Dy | RPT | VAL | ROS | KIL | SHA | BIR | DUB | CLA | MUL | CLO | BEL | MAL | weekday | WeekCheck | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Yr_Mo_Dy | |||||||||||||||
1 | 1969-07-17 06:40:00.000000000 | 14.847325 | 12.914560 | 13.299624 | 7.199498 | 11.667734 | 8.054839 | 11.819355 | 9.512047 | 9.543208 | 10.053566 | 14.550520 | 18.028763 | 2.989247 | 0.284946 |
2 | 1969-08-17 07:50:33.070866142 | 13.710906 | 12.111122 | 12.879132 | 6.942411 | 11.551772 | 7.633858 | 11.206024 | 9.341437 | 9.313169 | 9.518051 | 13.728898 | 17.156142 | 3.005906 | 0.287402 |
3 | 1969-09-14 12:00:00.000000000 | 13.158687 | 11.505842 | 12.648118 | 7.265907 | 11.554516 | 7.959409 | 11.310179 | 9.635896 | 9.700324 | 10.096953 | 13.810609 | 16.909317 | 3.000000 | 0.283154 |
4 | 1969-10-15 00:00:00.000000000 | 12.555648 | 10.429759 | 12.204815 | 6.898037 | 10.677667 | 7.441389 | 10.221315 | 8.909056 | 8.930870 | 9.158019 | 12.664759 | 14.937611 | 3.011111 | 0.288889 |
5 | 1969-11-14 12:00:00.000000000 | 11.724032 | 10.145619 | 11.550394 | 6.307487 | 10.224301 | 6.942061 | 8.797738 | 8.452903 | 8.040806 | 8.524857 | 12.767258 | 13.736039 | 2.982079 | 0.283154 |
✔ 모든 결측치는 컬럼기준 직전의 값으로 대체하고 첫번째 행에 결측치가 있을경우 뒤에있는 값으로 대채하라
df = df.fillna(method='ffill').fillna(method='bfill')
df.isnull().sum()
Yr_Mo_Dy 0
RPT 0
VAL 0
ROS 0
KIL 0
SHA 0
BIR 0
DUB 0
CLA 0
MUL 0
CLO 0
BEL 0
MAL 0
weekday 0
WeekCheck 0
dtype: int64
+ df.fillna(method='ffill') : 누락된 값(NA 또는 NaN)을 앞쪽으로 이전(non-null 값으로 채워진 이전 값)하여 채우는 역할. 'ffill'은 forward fill의 약자
+ df.fillna(method='bfill') : 누락된 값(NA 또는 NaN)을 뒤쪽으로 이후(non-null 값으로 채워진 다음 값)하여 채우는 역할. 'bfill'은 backward fill의 약자
✔ 년도 - 월을 기준으로 모든 컬럼의 평균값을 구하여라
Ans = df.groupby(df.Yr_Mo_Dy.dt.to_period('M')).mean()
Ans.head()
Yr_Mo_Dy | RPT | VAL | ROS | KIL | SHA | BIR | DUB | CLA | MUL | CLO | BEL | MAL | weekday | WeekCheck | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Yr_Mo_Dy | |||||||||||||||
1961-01 | 1961-01-16 00:00:00 | 14.932581 | 12.084194 | 13.431613 | 7.736774 | 11.215806 | 8.588065 | 11.184839 | 9.270968 | 9.085806 | 10.107419 | 13.880968 | 14.703226 | 2.935484 | 0.290323 |
1961-02 | 1961-02-14 12:00:00 | 16.269286 | 14.975357 | 14.324643 | 9.116786 | 13.852143 | 10.937500 | 11.890714 | 11.846071 | 11.821429 | 12.714286 | 18.583214 | 15.411786 | 3.000000 | 0.285714 |
1961-03 | 1961-03-16 00:00:00 | 11.015806 | 11.296452 | 10.752903 | 7.137742 | 10.509355 | 8.866774 | 9.644194 | 9.829677 | 10.646129 | 11.251935 | 16.410968 | 15.637742 | 3.000000 | 0.258065 |
1961-04 | 1961-04-15 12:00:00 | 10.722667 | 9.427667 | 9.998000 | 5.830667 | 8.435000 | 6.495000 | 6.925333 | 7.094667 | 7.342333 | 7.237000 | 11.147333 | 10.278333 | 3.166667 | 0.333333 |
1961-05 | 1961-05-16 00:00:00 | 9.860968 | 8.735161 | 10.818065 | 5.892258 | 9.490323 | 6.574839 | 7.477097 | 8.177097 | 8.039355 | 8.499355 | 11.900323 | 12.011613 | 2.806452 | 0.258065 |
✔ RPT 컬럼의 값을 일자별 기준으로 1차차분하라
df['RPT'].diff()
0 NaN
1 -0.33
2 3.79
3 -7.92
4 2.75
...
6569 3.75
6570 -4.37
6571 0.79
6572 4.50
6573 1.83
Name: RPT, Length: 6574, dtype: float64
+ .diff() : 이전 행과의 차이(차분)를 계산하는 메서드
✔ RPT와 VAL의 컬럼을 일주일 간격으로 각각 이동평균한값을 구하여라
df[['RPT', 'VAL']].rolling(7).mean()
RPT | VAL | |
---|---|---|
0 | NaN | NaN |
1 | NaN | NaN |
2 | NaN | NaN |
3 | NaN | NaN |
4 | NaN | NaN |
... | ... | ... |
6569 | 11.868571 | 9.362857 |
6570 | 11.904286 | 9.595714 |
6571 | 13.017143 | 10.011429 |
6572 | 13.285714 | 10.118571 |
6573 | 14.951429 | 11.801429 |
6574 rows × 2 columns
+ .rolling() : 이동 윈도우(moving window)를 적용하여 이동 통계량을 계산하는 메서드
DataSet
서울시 미세먼지 데이터 : https://www.airkorea.or.kr/web/realSearch?pMENU_NO=97
DataUrl = ‘https://raw.githubusercontent.com/Datamanim/pandas/main/seoul_pm.csv%E2%80%99
Question
df = pd.read_csv('https://raw.githubusercontent.com/Datamanim/pandas/main/seoul_pm.csv')
✔ 년-월-일:시 컬럼을 pandas에서 인식할 수 있는 datetime 형태로 변경하라. 서울시의 제공데이터의 경우 0시가 24시로 표현된다
def change_date(x):
import datetime
hour = x.split(':')[1]
date = x.split(':')[0]
if hour =='24':
hour ='00:00:00'
FinalDate = pd.to_datetime(date +" "+hour) + datetime.timedelta(days=1)
# 1일 후의 날짜 계산
else:
hour = hour +':00:00'
FinalDate = pd.to_datetime(date +" "+hour)
return FinalDate
df['(년-월-일:시)'] = df['(년-월-일:시)'].apply(change_date)
Ans = df
Ans.head()
(년-월-일:시) | PM10등급 | PM10 | PM2.5등급 | PM2.5 | 오존등급 | 오존 | 이산화질소등급 | 이산화질소 | 일산화탄소등급 | 일산화탄소 | 아황산가스등급 | 아황산가스 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2021-05-15 15:00:00 | 보통 | 47.0 | 보통 | 19.0 | 좋음 | 0.017 | 좋음 | 0.023 | 좋음 | 0.4 | 좋음 | 0.003 |
1 | 2021-05-15 14:00:00 | 보통 | 43.0 | 보통 | 20.0 | 좋음 | 0.024 | 좋음 | 0.019 | 좋음 | 0.3 | 좋음 | 0.003 |
2 | 2021-05-15 13:00:00 | 보통 | 34.0 | 보통 | 24.0 | 보통 | 0.035 | 좋음 | 0.017 | 좋음 | 0.4 | 좋음 | 0.004 |
3 | 2021-05-15 12:00:00 | 보통 | 41.0 | 보통 | 27.0 | 보통 | 0.037 | 좋음 | 0.020 | 좋음 | 0.4 | 좋음 | 0.004 |
4 | 2021-05-15 11:00:00 | 보통 | 51.0 | 보통 | 34.0 | 보통 | 0.033 | 좋음 | 0.023 | 좋음 | 0.4 | 좋음 | 0.005 |
✔ 일자별 영어요일 이름을 dayName 컬럼에 저장하라
df['dayName'] = df['(년-월-일:시)'].dt.day_name()
df['dayName']
0 Saturday
1 Saturday
2 Saturday
3 Saturday
4 Saturday
...
1234 Thursday
1235 Thursday
1236 Thursday
1237 Thursday
1238 Thursday
Name: dayName, Length: 1239, dtype: object
✔ 일자별 각 PM10등급의 빈도수를 파악하라
Ans1 = df.groupby(['dayName','PM10등급'], as_index=False).size()
Ans2 = Ans1.pivot(index='dayName',columns='PM10등급',values='size').fillna(0)
display(Ans1.head())
display(Ans2)
dayName | PM10등급 | size | |
---|---|---|---|
0 | Friday | 나쁨 | 31 |
1 | Friday | 매우나쁨 | 17 |
2 | Friday | 보통 | 120 |
3 | Friday | 좋음 | 21 |
4 | Monday | 나쁨 | 1 |
PM10등급 | 나쁨 | 매우나쁨 | 보통 | 좋음 |
---|---|---|---|---|
dayName | ||||
Friday | 31.0 | 17.0 | 120.0 | 21.0 |
Monday | 1.0 | 21.0 | 83.0 | 63.0 |
Saturday | 31.0 | 27.0 | 71.0 | 54.0 |
Sunday | 2.0 | 1.0 | 67.0 | 98.0 |
Thursday | 41.0 | 0.0 | 144.0 | 5.0 |
Tuesday | 13.0 | 10.0 | 71.0 | 74.0 |
Wednesday | 26.0 | 0.0 | 95.0 | 46.0 |
✔ 시간이 연속적으로 존재하며 결측치가 없는지 확인하라
check = len(df['(년-월-일:시)'].diff().unique()) # 해당 시간 간격 열에 얼마나 다양한 값이 있는지
if check == 2 :
# [NaT, '-1 days +23:00:00']
Ans = True
else :
Ans = False
Ans
True
+ diff() : 이전 행과의 차이를 계산한 결과를 반환.
✔ 오전 10시와 오후 10시(22시)의 PM10의 평균값을 각각 구하여라
am_10_data = df.loc[df['(년-월-일:시)'].dt.hour == 10]
pm_10_data = df.loc[df['(년-월-일:시)'].dt.hour == 22]
am_10_pm10_mean = am_10_data['PM10'].mean()
pm_10_pm10_mean = pm_10_data['PM10'].mean()
✔ 날짜 컬럼을 index로 만들어라
df.set_index('(년-월-일:시)',inplace=True,drop=True)
Ans =df
Ans.head()
PM10등급 | PM10 | PM2.5등급 | PM2.5 | 오존등급 | 오존 | 이산화질소등급 | 이산화질소 | 일산화탄소등급 | 일산화탄소 | 아황산가스등급 | 아황산가스 | dayName | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
(년-월-일:시) | |||||||||||||
2021-05-15 15:00:00 | 보통 | 47.0 | 보통 | 19.0 | 좋음 | 0.017 | 좋음 | 0.023 | 좋음 | 0.4 | 좋음 | 0.003 | Saturday |
2021-05-15 14:00:00 | 보통 | 43.0 | 보통 | 20.0 | 좋음 | 0.024 | 좋음 | 0.019 | 좋음 | 0.3 | 좋음 | 0.003 | Saturday |
2021-05-15 13:00:00 | 보통 | 34.0 | 보통 | 24.0 | 보통 | 0.035 | 좋음 | 0.017 | 좋음 | 0.4 | 좋음 | 0.004 | Saturday |
2021-05-15 12:00:00 | 보통 | 41.0 | 보통 | 27.0 | 보통 | 0.037 | 좋음 | 0.020 | 좋음 | 0.4 | 좋음 | 0.004 | Saturday |
2021-05-15 11:00:00 | 보통 | 51.0 | 보통 | 34.0 | 보통 | 0.033 | 좋음 | 0.023 | 좋음 | 0.4 | 좋음 | 0.005 | Saturday |
+ inplace = True : 원본 DataFrame 변경
+ drop = True : 인덱스로 설정한 열을 DataFrame의 컬럼에서 제거
✔ 데이터를 주단위로 뽑아서 최소,최대 평균, 표준표차를 구하여라
import numpy as np
numeric_cols = df.select_dtypes(include=[np.number]).columns
Ans = df[numeric_cols].resample('W').agg(['min','max','mean','std'])
Ans.head()
PM10 | PM2.5 | 오존 | ... | 이산화질소 | 일산화탄소 | 아황산가스 | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
min | max | mean | std | min | max | mean | std | min | max | ... | mean | std | min | max | mean | std | min | max | mean | std | |
(년-월-일:시) | |||||||||||||||||||||
2021-03-28 | 6.0 | 160.0 | 72.747368 | 43.345462 | 4.0 | 113.0 | 44.705263 | 29.551928 | 0.002 | 0.085 | ... | 0.044579 | 0.023722 | 0.3 | 1.4 | 0.611579 | 0.232408 | 0.002 | 0.006 | 0.003274 | 0.000961 |
2021-04-04 | 3.0 | 598.0 | 97.148810 | 129.911976 | 1.0 | 120.0 | 23.168675 | 22.399578 | 0.003 | 0.055 | ... | 0.027929 | 0.014978 | 0.3 | 0.9 | 0.445833 | 0.135741 | 0.002 | 0.004 | 0.002732 | 0.000541 |
2021-04-11 | 17.0 | 102.0 | 41.059524 | 16.325911 | 7.0 | 70.0 | 21.761905 | 11.479343 | 0.009 | 0.070 | ... | 0.022583 | 0.009562 | 0.3 | 0.7 | 0.389286 | 0.087573 | 0.002 | 0.004 | 0.002744 | 0.000569 |
2021-04-18 | 3.0 | 367.0 | 48.180723 | 43.254468 | 2.0 | 38.0 | 17.066265 | 7.867952 | 0.002 | 0.070 | ... | 0.023753 | 0.013553 | 0.3 | 0.6 | 0.386747 | 0.084954 | 0.002 | 0.004 | 0.002464 | 0.000579 |
2021-04-25 | 17.0 | 126.0 | 55.119048 | 26.659936 | 7.0 | 61.0 | 26.392857 | 13.094788 | 0.006 | 0.090 | ... | 0.028571 | 0.014640 | 0.3 | 0.8 | 0.457143 | 0.122142 | 0.001 | 0.011 | 0.003631 | 0.001763 |
5 rows × 24 columns
+ select_dtypes(include=[np.number]) : 데이터 타입에 대한 열들을 선택, [np.number]를 include 매개변수에 사용하여 숫자형 데이터 타입만 포함하도록 지정
+ columns : 선택된 열의 이름을 할당
+ .resample('W'): 주 단위로 데이터 집계
'🥇 certification logbook' 카테고리의 다른 글
[python 통계분석] t-test 검정 (0) | 2023.06.18 |
---|---|
[python 데이터 전처리] 데이터 스케일링 (data scaling) (0) | 2023.06.15 |
[python 데이터 핸들링] 판다스 연습 튜토리얼 - 07_Merge , Concat (0) | 2023.06.15 |
[python 데이터 핸들링] 판다스 연습 튜토리얼 - 06_Pivot (0) | 2023.06.15 |
[python 데이터 핸들링] 판다스 연습 튜토리얼 - 04_Apply , Map (0) | 2023.06.13 |
[python 데이터 핸들링] 판다스 연습 튜토리얼 - 03_Grouping (0) | 2023.06.13 |
[python 데이터 핸들링] 판다스 연습 튜토리얼 - 02 Filtering & Sorting (0) | 2023.06.09 |
[python 데이터 핸들링] 판다스 연습 튜토리얼 - 01 Getting & Knowing Data (0) | 2023.06.08 |