많은 열이있는 거대한 데이터 프레임이 있으며 그중 많은 유형이 datetime.datetime
있습니다. 문제는 많은 사람들이 예를 들어 datetime.datetime
값과 None
값 (및 잠재적으로 다른 유효하지 않은 값)을 포함한 혼합 유형을 가지고 있다는 것입니다 .
0 2017-07-06 00:00:00
1 2018-02-27 21:30:05
2 2017-04-12 00:00:00
3 2017-05-21 22:05:00
4 2018-01-22 00:00:00
...
352867 2019-10-04 00:00:00
352868 None
352869 some_string
Name: colx, Length: 352872, dtype: object
따라서 object
유형 열이 생성 됩니다. 이것은로 해결할 수 있습니다 df.colx.fillna(pd.NaT)
. 문제는 데이터 프레임이 너무 커서 개별 열을 검색 할 수 없다는 것입니다.
또 다른 방법은을 사용하는 pd.to_datetime(col, errors='coerce')
것이지만 datetime
숫자 값이 포함 된 많은 열로 캐스트 됩니다.
df.fillna(float('nan'), inplace=True)
날짜를 포함하는 열이 여전히 object
유형이며 여전히 동일한 문제가 있지만 을 수행 할 수도 있습니다.
나는 날짜에 캐스트에 따를 수있는 어떤 방법 해당 값이 정말 포함 않는 열의 datetime
값을, 또한 포함 할 수있다 None
, 잠재적으로 일부 잘못된 값 (언급은 그렇지 않으면 이후 pd.to_datetime
A의 try
/ except
절 할 것)? 유연한 버전과 같은 것pd.to_datetime(col)
답변
내가 볼 수있는 주요 문제는 숫자 값을 구문 분석 할 때입니다.
먼저 문자열로 변환 할 것을 제안합니다.
설정
dat = {
'index': [0, 1, 2, 3, 4, 352867, 352868, 352869],
'columns': ['Mixed', 'Numeric Values', 'Strings'],
'data': [
['2017-07-06 00:00:00', 1, 'HI'],
['2018-02-27 21:30:05', 1, 'HI'],
['2017-04-12 00:00:00', 1, 'HI'],
['2017-05-21 22:05:00', 1, 'HI'],
['2018-01-22 00:00:00', 1, 'HI'],
['2019-10-04 00:00:00', 1, 'HI'],
['None', 1, 'HI'],
['some_string', 1, 'HI']
]
}
df = pd.DataFrame(**dat)
df
Mixed Numeric Values Strings
0 2017-07-06 00:00:00 1 HI
1 2018-02-27 21:30:05 1 HI
2 2017-04-12 00:00:00 1 HI
3 2017-05-21 22:05:00 1 HI
4 2018-01-22 00:00:00 1 HI
352867 2019-10-04 00:00:00 1 HI
352868 None 1 HI
352869 some_string 1 HI
해결책
df.astype(str).apply(pd.to_datetime, errors='coerce')
Mixed Numeric Values Strings
0 2017-07-06 00:00:00 NaT NaT
1 2018-02-27 21:30:05 NaT NaT
2 2017-04-12 00:00:00 NaT NaT
3 2017-05-21 22:05:00 NaT NaT
4 2018-01-22 00:00:00 NaT NaT
352867 2019-10-04 00:00:00 NaT NaT
352868 NaT NaT NaT
352869 NaT NaT NaT
답변
이 함수는 열의 값이 정규식 패턴 (\ d {4}-\ d {2}-\ d {2}) +와 일치하는 경우 열의 데이터 유형을 datetime으로 설정합니다 (예 : 2019-01-01). ). 마스크를 설정하고 적용하는 데 도움이 되는 모든 Pandas DataFrame 열 및 필터에서 문자열 을 검색 하는 방법에 대한이 답변을 참조 하십시오.
def presume_date(dataframe):
""" Set datetime by presuming any date values in the column
indicates that the column data type should be datetime.
Args:
dataframe: Pandas dataframe.
Returns:
Pandas dataframe.
Raises:
None
"""
df = dataframe.copy()
mask = dataframe.astype(str).apply(lambda x: x.str.match(
r'(\d{4}-\d{2}-\d{2})+').any())
df_dates = df.loc[:, mask].apply(pd.to_datetime, errors='coerce')
for col in df_dates.columns:
df[col] = df_dates[col]
return df
사용 제안에서 작업하면 dateutil
도움이 될 수 있습니다. 열에 날짜와 같은 값이 있으면 열이 날짜 시간이어야한다고 가정합니다. 더 빠른 다른 데이터 프레임 반복 방법을 고려하려고했습니다. Pandas의 DataFrame에서 행을 반복하는 방법에 대한이 대답 은 잘 설명했습니다.
참고 dateutil.parser
없음 년 하루 값 ’12월’또는 ‘2019 11월’와 같은 임의의 문자열을 현재 하루 해 사용합니다.
import pandas as pd
import datetime
from dateutil.parser import parse
df = pd.DataFrame(columns=['are_you_a_date','no_dates_here'])
df = df.append(pd.Series({'are_you_a_date':'December 2015','no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':'February 27 2018','no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':'May 2017 12','no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':'2017-05-21','no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':None,'no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':'some_string','no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':'Processed: 2019/01/25','no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':'December','no_dates_here':'just a string'}), ignore_index=True)
def parse_dates(x):
try:
return parse(x,fuzzy=True)
except ValueError:
return ''
except TypeError:
return ''
list_of_datetime_columns = []
for row in df:
if any([isinstance(parse_dates(row[0]),
datetime.datetime) for row in df[[row]].values]):
list_of_datetime_columns.append(row)
df_dates = df.loc[:, list_of_datetime_columns].apply(pd.to_datetime, errors='coerce')
for col in list_of_datetime_columns:
df[col] = df_dates[col]
의 datatime 값을 사용하려는 경우 다음을 dateutil.parser
추가 할 수 있습니다.
for col in list_of_datetime_columns:
df[col] = df[col].apply(lambda x: parse_dates(x))