데이터 전처리/python

날짜,시간 데이터 전처리 (feat. Series,Dataframe)

JSMATH 2024. 4. 19. 22:45

df_merged_mean.csv
0.00MB

*위의 파일을 이용하여 날짜와 시간 데이터 전처리하였습니다.

import pandas as pd
import numpy as np
#df_merged_mean = pd.read_csv('파일위치주소',encoding='UFT-8 또는 CP949')

주소가 어디인지 모르시는 분들은 아래의 글을 참고해주세요.

https://pastryofjsmath.tistory.com/23

 

파이썬 데이터프레임 불러오기(txt->csv->read.csv)

우리는 대게 excel(xsl),txt 데이터에서 우리는 정보를 얻습니다. txt는 데이터를 받으면 헤더부분이나 따로 떼어두는 경우도 있기 때문에.. 간혹 사용한다고 합니다. 그리고 csv파일로 바꾸는 이유는

pastryofjsmath.tistory.com

pd.to_datetime()에서 Series,Dataframe에 대한 문제점은 맨 밑에 다루었습니다.

df_merged_mean의 데이터

우선 맨 1열의 Unnamed:0가 거슬리니 제거합니다.

df_merged_mean.drop('Unnamed: 0',axis=1)

df_merged_mean의 데이터-2

이제 강의시작시간과 개강일 마지막으로 종강일을 처리하고 종강일과 개강일의 차이 총 일수를 체크해보겠습니다.

 

pd.to_datetime을 사용하려면 일정 표준화된 형식을 지켜줘야 합니다.

하지만 선형대수학 행의 강의시작시간이 '30분'이 붙어 있어서 표준화되어 있지 않습니다.  그렇다면 남은 곳에서도 '00분'을 시켜주면 되겠습니다. 13시 00분 같이 말이죠.

#일정한 규칙이 없으므로, 규칙을 아예 만들어버리자. ~시 ~분
df_merged_mean['강의시작시간']=df_merged_mean['강의시작시간'].str.extract(r'(\d+시)').fillna('00시')+df_merged_mean['강의시작시간'].str.extract(r'(\d+분)').fillna('00분')

df[col].str.extract(r'(data)') 는 df의 col에서 data가 포함되어있으면 모두 추출해버리는 방법이다.

df_merged_mean['강의시작시간'].str.extract(r'(시)')이면,  df_merged_mean['강의시작시간']의 모든 '시'를 뽑아내는거죠.

근데 거기에 '몇'이라는 수치가 있으니까 \d(정수)를 해서 '\d시'라고 나타내는거죠.

어떠한 규칙(시,분)으로 모든 행을 나타냄

위와 같이 나타냈으면, pd.to_datetime에서 format을 제대로 사용 할 수 있습니다.

만약 초단위는 필요 없다 싶으시면, .dt.strftime('%H:%M')이렇게 사용하시면 됩니다.

pd.to_datetime(df_merged_mean['강의시작시간'],format='%H시%M분').dt.time

pd.to_datetime(df_merged_mean['강의시작시간'],format='%H시%M분').dt.strftime('%H:%M')

df_merged_mean['강의시작시간']=pd.to_datetime(df_merged_mean['강의시작시간'],format='%H시%M분').dt.strftime('%H:%M')
df_merged_mean

 

강의시작시간

다음은 개강일입니다. 개강일은 두가지 버전이 있습니다.

1.문자로 타입을 변경 후 글자 추출.

2.pd.to_datetime

1.문자로 타입을 변경 후 글자 추출.

우선 문자인지 확인을 해야합니다. df.dtypes를 해주어 object인지 확인해주세요. 그리고 .str[] 위치를 찾아 문자를 결합해주심 됩니다.

 

df_merged_mean['개강일']=df_merged_mean['개강일'].astype('str')
df_merged_mean['개강일'].str[0:2] + "-" +df_merged_mean['개강일'].str[2:4] + "-" +df_merged_mean['개강일'].str[4:]

 

두번째로는 pd.datetime입니다.

pd.datetime은 항상 형태를 맞춰줘야합니다. format이 xxxx년 xx월 xx일 xx시xx분xx초의 규격을 맞춰두었기 때문에, 이렇게 데이터를 만들어줘야합니다.

df_merged_mean['개강일']

df_merged_mean['개강일']='20' + df_merged_mean['개강일']

df_merged_mean['개강일']

pd.to_datetime(df_merged_mean['개강일'],format = '%Y%m%d')

개강일까지 처리

다음은 종강일입니다. 

*수정(240508): str로 변환하지 않고 format자체를 아래와 같이 변경하시면 바로 가능합니다.

pd.to_datetime(df2['종강일'],format='%Y년%m월%d일')

또는 번거롭지만 원래 하던대로 str[위치]를 사용하여 했습니다.

이제 형태가 갖추어졌으니 df[col].str[]+"-"df[col].str[] 이런식으로 나타내던가 pd.to_datetime으로 하시면 되겠습니다,

종강일까지 완료

마지막으로 날짜 남은 계산을 하는 방법입니다. pd.to_datetime으로 하셨다면, 두 컬의 차로 바로 가능합니다.

df_merged_mean['개강일']=pd.to_datetime(df_merged_mean['개강일'],format = '%Y%m%d')

df_merged_mean


df_merged_mean['종강일'].str[0:2]+df_merged_mean['종강일'].str[3:5]+df_merged_mean['종강일'].str[6:8]

'20'+df_merged_mean['종강일'].str[0:2]+df_merged_mean['종강일'].str[4:5]+df_merged_mean['종강일'].str[6:8]

df_merged_mean

df_merged_mean['종강일'] = '20'+df_merged_mean['종강일'].str[0:2]+'0'+df_merged_mean['종강일'].str[4:5]+df_merged_mean['종강일'].str[6:8]

df_merged_mean.dtypes

pd.to_datetime(df_merged_mean['종강일'],format='%Y%m%d')

df_merged_mean['종강일']=pd.to_datetime(df_merged_mean['종강일'],format='%Y%m%d')

df_merged_mean.dtypes

df_merged_mean

df_merged_mean['종강일']-df_merged_mean['개강일']

df_merged_mean['남은일수']=df_merged_mean['종강일']-df_merged_mean['개강일']

df_merged_mean

 

다음엔 R로 전처리하는 내용도 올려보겠습니다. 

*240515 추가하였습니다.

https://pastryofjsmath.tistory.com/35

 

날짜 데이터 전처리 [in R]

https://pastryofjsmath.tistory.com/28 날짜,시간 데이터 전처리*위의 파일을 이용하여 날짜와 시간 데이터 전처리하였습니다.import pandas as pdimport numpy as np#df_merged_mean = pd.read_csv('파일위치주소',encoding='UFT

pastryofjsmath.tistory.com

 

++240610

단일 col로 pd.to_datetime()하는 것과 기존 df['강의시작시간']으로 다시 지정해서 하는 것은 결과가 같아야하는데 단일 col로 지정하면 오류가 발생합니다. 찾아본 결과 Series,Dataframe의 차이때문이라고 합니다.

import pandas as pd
import numpy as np
#df_merged_mean = pd.read_csv('파일위치주소',encoding='UFT-8 또는 CP949')

start_time = df_merged_mean['강의시작시간'].str.extract(r'(\d+시)')+df_merged_mean['강의시작시간'].str.extract(r'(\d+분)').fillna('00분')
#start_time으로 pd.to_datetime()사용하면 오류발생.

type(start_time)
#pandas.core.frame.DataFrame
#AttributeError: 'int' object has no attribute 'lower'

#해결방법
#df.squeeze() : 단일 컬로 축소.

start_time = start_time.squeeze()
#pandas.core.series.Series

pd.to_datetime(start_time,format='%H시%M분').dt.time
0    13:00:00
1    10:30:00
2    12:00:00
3    15:00:00
4    14:00:00
5    09:00:00
Name: 0, dtype: object

#그냥 기존에 있던 컬에 넣어버리면 문제가 안됨.
df['강의시작시간'] = df['강의시작시간'].str.extract(r'(\d+시)')+df['강의시작시간'].str.extract(r'(\d+분)').fillna('00분')
pd.to_datetime(df['강의시작시간'],format='%H시%M분').dt.time
0    13:00:00
1    10:30:00
2    12:00:00
3    15:00:00
4    14:00:00
5    09:00:00
Name: 강의시작시간, dtype: object

왜 기존 컬에 넣으면 가능한지 보니 아래와 같이 나옵니다.

type(df['강의시작시간'])
#pandas.core.series.Series

그러니까 pd.to_datetime()은 데이터프레임은 안먹히고 시리즈형태로 squeeze()해주어야만 합니다!