कौन से कॉलम डेटाइम हैं


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_datetimeएक try/ exceptखंड में क्या होगा) का उल्लेख करना? के लचीले संस्करण की तरह कुछpd.to_datetime(col)


क्या ऑब्जेक्ट DataFrame प्रकार में संग्रहीत हैं datetime.datetimeया pandas._libs.tslibs.timestamps.Timestamp? यदि पूर्व में मेरी सिफारिश है कि जो कुछ भी pandasबेहतर तरीके से हैंडल करता है उसको डेटाइम बनाया जाए ।
एलोलज

क्या Noneआपके कॉलम में, वास्तविक Noneया स्ट्रिंग प्रतिनिधि हैं?
इरफान

वे हैं None, स्ट्रिंग नहीं। संभावित वहाँ भी गलत मान हो सकता है ... @erfan
yatu

3
तब मुझे आश्चर्य होता है, कि आपके डेटाबेस में sql मॉडल कैसा है? चूँकि sql कुछ विशेष प्रकार के स्तंभों को बाध्य करता है। आप मिश्रित प्रकार के कॉलम के साथ कैसे समाप्त हुए? क्या आप शायद ऐसा कॉलम भी दिखा सकते हैं जो उसमें datetimeऔर valuesउसमें है?
इरफान

1
डेटाइम का अनुमान लगाने के लिए डेटूटिल पार्सर का उपयोग करें। कई की दहलीज सेट किया जा सकता (कहते हैं कि 5 दिनांकों) कॉलम में सुनिश्चित करने के लिए stackoverflow.com/questions/9507648/...
सर्ज

जवाबों:


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_datetimeऔर coerceत्रुटियों, वहाँ कई हैं। समस्या संख्यात्मक स्तंभों के साथ थी। लेकिन यह मेरे लिए नहीं हुआ है कि स्ट्रिंग के लिए डाले गए संख्यात्मक कॉलम पांडा द्वारा पार्स नहीं किए जाते हैं to_datetime। ' बहुत बहुत धन्यवाद, यह वास्तव में मदद करता है!
yatu

4

यह फ़ंक्शन डेटा कॉलम को डेटाटाइम में सेट करेगा, यदि कॉलम में कोई मान regex पैटर्न (\ d {4} - \ d {2} - \ d {2}) + (जैसे 2019-01-01) से मेल खाता है )। सभी पंडों के डेटाफ़्रेम कॉलम और फ़िल्टर की खोज करने के तरीके पर इस उत्तर का श्रेय, जो मास्क को सेट करने और लगाने में मदद करता है।

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, इससे मदद मिल सकती है। यह अभी भी अनुमान पर काम कर रहा है कि यदि किसी स्तंभ में कोई दिनांक-जैसे मान हैं, तो स्तंभ एक डेटाइम होना चाहिए। मैंने विभिन्न डेटाफ्रेम पुनरावृत्तियों के तरीकों पर विचार करने की कोशिश की, जो तेज हैं। मुझे लगता है कि पंडों में एक डेटाफ्रेम में पंक्तियों पर पुनरावृति कैसे करें, इस उत्तर ने उनका वर्णन करने में अच्छा काम किया।

ध्यान दें कि dateutil.parserकिसी भी वर्ष या दिन के मान के साथ 'दिसंबर' या 'नवंबर 2019' जैसे किसी भी तार के लिए वर्तमान दिन या वर्ष का उपयोग करेंगे।

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]

यदि आप डेटामेट मान का उपयोग करना चाहते हैं dateutil.parser, तो आप इसे जोड़ सकते हैं:

for col in list_of_datetime_columns:
    df[col] = df[col].apply(lambda x: parse_dates(x))

यह एक अच्छा विचार है, लेकिन दुर्भाग्य से मैं ऐसी चीज की तलाश कर रहा हूं जो संभावित रूप से कई अलग-अलग डेटाइम प्रारूपों के लिए सामान्यीकरण कर सकती है, इसलिए प्रारूप को हार्डकोड किए बिना। प्रयास हालांकि सराहना
yatu

@yatu कोई समस्या नहीं है - मैं सिर्फ उस चीज पर काम कर रहा हूं जिसकी जरूरत है। मुझे आश्चर्य है कि क्या आप सभी डेटाइम फॉर्मेट को सामान्य कर सकते हैं? आपको उन सभी प्रारूपों के लिए समय से पहले खाते की आवश्यकता हो सकती है जिन्हें आप देखने की उम्मीद करेंगे; या, सभी प्रारूप जिन्हें आप मान्य डेटाइम मानते हैं।
हाँ, यह रिक

@ आपका वास्तव में @Serge dateutilद्वारा उल्लिखित मॉड्यूल ऐसा लगता है कि यह उपयोगी हो सकता है।
हाँ, यह रिक

@yatu कृपया मेरा अद्यतन उत्तर देखें। मैं dateutil.parseकई तरह के डेट स्ट्रिंग्स की पहचान करता था।
हाँ, यह रिक

अछा लगता है! अब ज्यादा समय नहीं है, जैसा कि मैंने यह कर सकते हैं @yes ही एक बार देख ले जाएगा
yatu
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.