কোন কলামগুলি তারিখের সময় তা অন্তর্ভুক্ত করুন


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 কাস্ট করতে অনুসরণ করতে পারে যারা কলাম যার মান সত্যিই ধারণ না datetimeমান, কিন্তু থাকতে পারে None, এবং সম্ভাব্য কিছু অবৈধ মান (উল্লেখ অন্যথায় একটি যেহেতু pd.to_datetimeএকটি try/ exceptদফা করবেন)? এর নমনীয় সংস্করণের মতো কিছুpd.to_datetime(col)


তথ্য ফ্রেমটি কি ডাটাফ্রেমে টাইপের মধ্যে সংরক্ষণ করা হয় datetime.datetimeবা pandas._libs.tslibs.timestamps.Timestamp? যদি পূর্বের আমার সুপারিশটি হ'ল ডেটটাইম যা কিছু তৈরি হয়েছে তা পরিবর্তনের জন্য এটি pandasআরও ভালভাবে পরিচালনা করে।
ALOLZ

হয় Noneআপনার কলামে, প্রকৃত Noneএটি বা স্ট্রিং প্রতিনিধিদের?
এরফান

তারা Noneস্ট্রিং নয়। সম্ভবত ভুল মানগুলিও হতে পারে ... @ স্পফান
ইয়াতু

3
তারপরে আমি অবাক হই, আপনার ডাটাবেসে স্কেল মডেলটি কেমন? যেহেতু এসকিএল নির্দিষ্ট ধরণের কলামগুলিকে জোর করে। আপনি মিশ্র টাইপের কলামগুলি কীভাবে শেষ করলেন? আপনি হয়তো একটি কলাম যা দেখাতে পারেন datetimeএবং valuesএতে?
এরফান

1
তারিখের সময় অনুমান করতে ডেটুটিল পার্সার ব্যবহার করুন। নিশ্চিত হতে স্ট্যাকওভারফ্লো.com
সার্জ করুন

উত্তর:


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। অনেক ধন্যবাদ, এটি সত্যিই সাহায্য করে!
ইয়াতু

4

এই ফাংশনটি কলামের ডেটা ধরণের তারিখকে সেট করবে, যদি কলামের কোনও মান রেজেক্স প্যাটার্নের সাথে মেলে (\ 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))

এটি একটি দুর্দান্ত ধারণা, তবে দুর্ভাগ্যক্রমে আমি এমন কিছু সন্ধান করছি যা সম্ভাব্য বিভিন্ন ডেটটাইম ফর্ম্যাটগুলিতে সাধারণীকরণ করতে পারে, সুতরাং বিন্যাসটিকে হার্ডকড না করে।
চেষ্টাটির

@ ইয়াতু কোনও সমস্যা নয় - আমি এমন কিছু ঘটতে কাজ করলাম যা এর প্রয়োজন ছিল। আমি ভাবছি আপনি যদি সমস্ত ডেটটাইম ফর্ম্যাটগুলিতে সাধারণীকরণ করতে পারেন তবে? আপনি যে ফর্ম্যাটগুলি দেখতে আশা করছেন সেগুলির জন্য আপনাকে কেবল সময়ের আগে অ্যাকাউন্ট করতে হবে; বা, আপনি যে সমস্ত ফর্ম্যাটকে বৈধ তারিখের সময় বলে বিবেচনা করবেন সেগুলি সমস্ত।
হ্যাঁ এটি রিক

@ ইয়াতু আসলে @ সার্জ dateutilদ্বারা উল্লিখিত সেই মডিউলটি দেখে মনে হচ্ছে এটি কার্যকর হতে পারে।
হ্যাঁ এটি রিক

@ আয়তু দয়া করে আমার আপডেট হওয়া উত্তরটি দেখুন। আমি dateutil.parseবিভিন্ন ধরণের ডেট স্ট্রিং সনাক্ত করতে ব্যবহৃত হত ।
হ্যাঁ এটি রিক

ভাল লাগছে! এখনই খুব বেশি সময় নেই, আমি @
চোখের
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.