Hangi sütunların tarih olduğunu belirle


14

Birçoğu tür olan birçok sütun ile büyük bir veri çerçevesi var datetime.datetime. Sorun, birçoğunun, örneğin datetime.datetimedeğerler veNone değerler (ve potansiyel olarak diğer geçersiz değerler) :

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

Böylece bir object tip sütunu ile . Bu ile çözülebilir df.colx.fillna(pd.NaT). Sorun, veri çerçevesinin tek tek sütunları arayamayacak kadar büyük olmasıdır.

Başka bir yaklaşım kullanmak pd.to_datetime(col, errors='coerce') , ancak bu datetimesayısal değerler içeren birçok sütuna yayılacaktır .

Ben de yapabilirdim df.fillna(float('nan'), inplace=True) tarihleri içeren sütunlar hala olmasına rağmen, objecttürü ve hala aynı sorun olurdu.

Değerleri gerçekten değerler içeren datetimeancak aynı zamanda Nonebazı geçersiz değerler içerebilen (muhtemelen başka pd.to_datetimebir try/ exceptyan tümcesinde a ifadesi kullanacağından söz ederek) bu sütunları datetime uygulamak için hangi yaklaşımı izleyebilirim ? Esnek bir sürümü gibi bir şeypd.to_datetime(col)


Nesne DataFrame türünde saklanıyor mu datetime.datetimeveya pandas._libs.tslibs.timestamps.Timestamp? Eğer eski benim önerim datetime ne olursa olsun pandasbiraz daha iyi işleme türü değiştirmek için olurdu .
ALollz

Are Nonesütunlarınızdaki, fiili Nonebunun veya dize temsilcileri?
Erfan

Bunlar Nonedize değil. Potansiyel olarak yanlış değerler de olabilir ... @erfan
yatu

3
O zaman merak ediyorum, veritabanınızdaki sql modeli nasıl? Sql beri belirli sütun türleri zorlar. Nasıl karışık tip sütunlarla sonuçlandınız? İçinde datetimeve valuesiçinde olan bir sütunu da gösterebilir misiniz ?
Erfan

1
tarih saatini tahmin etmek için dateutil ayrıştırıcısını kullanın. Emin olmak için sütunda birkaç eşiğin (5 tarih diyelim) ayarlanabilir. Stackoverflow.com/questions/9507648/…
Serge

Yanıtlar:


1

Gördüğüm en temel sorun sayısal değerleri ayrıştırmak.

Önce dizelere dönüştürmeyi öneriyorum


Kurmak

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

Çözüm

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

Görünüşe göre bu sorunu büyük ölçüde basitleştiriyor. Bunu düşünmedim bile. İdeal senaryo basitçe uygulamaktı pd.to_datetimeve coercehatalar var, pek çok var. Sorun sayısal sütunlarla ilgiliydi. Ama dizeye dökülen sayısal sütunların pandalar tarafından ayrıştırılmadığı bana gelmedi to_datetime. Çok teşekkürler, bu gerçekten yardımcı oluyor!
yatu

4

Bu işlev, sütundaki herhangi bir değer normal ifade modeliyle eşleşiyorsa (\ d {4} - \ d {2} - \ d {2}) + (örn. 2019-01-01) bir sütunun veri türünü datetime olarak ayarlar. ). Tüm Pandas DataFrame sütunlarında Dize Nasıl Aranacağına ve maskenin ayarlanmasına ve uygulanmasına yardımcı olan filtreye verilen bu cevaba teşekkür edin.

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

Kullanmak için öneriden çalışmak dateutil, bu yardımcı olabilir. Bir sütunda tarih benzeri değerler varsa, sütunun datetime olması gerektiği varsayımı üzerinde hala çalışılmaktadır. Daha hızlı olan farklı veri çerçevesi yineleme yöntemlerini düşünmeye çalıştım. Ben Pandas bir DataFrame satırları üzerinde yineleme nasıl bu açıklamak onları iyi bir iş yaptı düşünüyorum.

dateutil.parserYıl veya gün değeri olmayan 'Aralık' veya 'Kasım 2019' gibi dizeler için geçerli günü veya yılı kullanacağınızı unutmayın .

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]

Adresindeki veri zamanı değerlerini de kullanmak dateutil.parseristerseniz bunu ekleyebilirsiniz:

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

Bu güzel bir fikir, ama ne yazık ki potansiyel olarak birkaç farklı datetime formatlarını genelleştirebilecek bir şey arıyorum, bu yüzden formatı zor kodlamadan. Yine de çaba için
teşekkür ederiz

@yatu Sorun değil - sadece buna ihtiyaç duyan bir şey üzerinde çalışıyordum. Acaba tüm datetime formatlarına genelleme yapabilir misiniz? Görmeyi beklediğiniz tüm formatları önceden hesaplamanız gerekebilir; veya geçerli tarih olarak değerlendireceğiniz tüm biçimler.
Evet, bu Rick

@yatu Aslında @Serge dateutiltarafından bahsedilen modül faydalı olabilir gibi görünüyor.
Evet, bu Rick

@yatu lütfen güncellenmiş cevabımı görün. Kullandığım dateutil.parsetarih dizeleri birçok farklı türde tanımlamak için.
Evet bu Rick

İyi görünüyor! şimdi fazla zamanım yok, en kısa sürede bir göz atacağım @yes
yatu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.