날짜 시간이 어떤 열인지 추론


14

많은 열이있는 거대한 데이터 프레임이 있으며 그중 많은 유형이 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_datetimeA의 try/ except절 할 것)? 유연한 버전과 같은 것pd.to_datetime(col)


개체가 DataFrame 유형에 저장된 datetime.datetimepandas._libs.tslibs.timestamps.Timestamp? 전자의 경우 권장 사항은 날짜 시간을 만든 항목을 pandas조금 더 잘 처리하는 유형으로 변경하는 것 입니다.
ALollz

있습니까 None당신의 열의, 실제 None그것의 또는 문자열 대표는?
Erfan

그들은 None문자열 이 아닙니다. 잠재적으로 잘못된 값이있을 수도 있습니다 ... @erfan
yatu

3
그런 다음 데이터베이스의 SQL 모델이 어떻습니까? sql은 특정 유형의 열을 강제 실행하기 때문입니다. 혼합 유형 열로 어떻게 끝났습니까? datetime그리고 그 values안에 있는 열을 보여줄 수 있습니까 ?
Erfan

1
dateutil 구문 분석기를 사용하여 날짜 시간을 추측하십시오. stackoverflow.com/questions/9507648/…을
Serge

답변:


1

내가 볼 수있는 주요 문제는 숫자 값을 구문 분석 할 때입니다.

먼저 문자열로 변환 할 것을 제안합니다.


설정

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

글쎄, 이것은 문제를 크게 단순화시키는 것처럼 보입니다. 나는 이것을 생각조차하지 않았다. 이상적인 시나리오는 단순히 적용하는 것이었다 pd.to_datetimecoerce많은 있기 때문에, 오류를. 숫자 열에 문제가있었습니다. 그러나 문자열에 캐스트 된 숫자 열이 pandas에 의해 구문 분석되지 않는 것은 나에게 발생하지 않았습니다 to_datetime. 정말 고마워요, 정말 도움이됩니다!
yatu

4

이 함수는 열의 값이 정규식 패턴 (\ 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))

이것은 좋은 생각이지만 불행히도 형식을 하드 코딩하지 않고 잠재적으로 여러 가지 다른 날짜 시간 형식으로 일반화 할 수있는 것을 찾고 있습니다. 그래도 노력을 주셔서 감사합니다
yatu

@yatu 문제가 아닙니다. 방금 필요한 작업을 진행했습니다. 그래도 모든 날짜 시간 형식으로 일반화 할 수 있는지 궁금합니다. 예상되는 모든 형식에 대해 미리 설명해야 할 수도 있습니다. 또는 유효한 날짜 / 시간으로 간주되는 모든 형식입니다.
네 이것은

@yatu 실제로 @Serge에서 dateutil언급 한 모듈은 유용 할 것 같습니다.
네 이것은

@ yatu 업데이트 된 답변을 참조하십시오. dateutil.parse여러 종류의 날짜 문자열을 식별하는 데 사용 했습니다.
그렇습니다 이것은

좋아 보인다! 지금 시간이 얼마 남지 않았습니다. @yes 가능한 한 빨리 살펴볼 것입니다.
yatu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.