使用平均值

时间:2015-12-31 21:58:47

标签: python datetime pandas

我有约会,我定期进入数据框。 数据通常是格式良好的,但有时在其他日期列中存在错误数据。

我总是期望以解析的9位数形式出现日期:

(tm_year=2000, tm_mon=11, tm_mday=30, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=335, tm_isdst=-1)
(2015, 12, 29, 0, 30, 50, 1, 363, 0)

我该如何检查并修复此问题?

我想要做的是替换任何不是日期的日期,日期基于表示last_update + 1/2更新间隔的变量,因此这些项目不会被后续函数过滤掉。

显示的数据是从feedparser发布的。

import pandas as pd
import datetime

# date with ugly data
df_date_ugly = pd.DataFrame({'date': [
                             (2015, 12, 29, 0, 30, 50, 1, 363, 0), 
                             (2015, 12, 28, 23, 59, 12, 0, 362, 0),
                            'None', '',
                             (2015, 12, 28, 23, 59, 12, 0, 362, 0)
                            ]})

# date is fine
df_date =  pd.DataFrame({'date': [
                             (2015, 12, 29, 0, 30, 50, 1, 363, 0), 
                             (2015, 12, 28, 23, 59, 12, 0, 362, 0),
                             (2015, 12, 28, 23, 59, 12, 0, 362, 0)
                            ]})

Pseudocode
  if the original_date is valid
     return original_date
  else
     return substitute_date

2 个答案:

答案 0 :(得分:3)

import calendar
import numpy as np
import pandas as pd

def tuple_to_timestamp(x):
    try:
        return calendar.timegm(x)               # 1
    except (TypeError, ValueError):
        return np.nan

df = pd.DataFrame({'orig': [
    (2015, 12, 29, 0, 30, 50, 1, 363, 0), 
    (2015, 12, 28, 23, 59, 12, 0, 362, 0),
    'None', '',
    (2015, 12, 30, 23, 59, 12, 0, 362, 0)]})

ts = df['orig'].apply(tuple_to_timestamp)       # 2
# 0    1451349050
# 1    1451347152
# 2           NaN
# 3           NaN
# 4    1451519952
# Name: orig, dtype: float64

ts = ts.interpolate()                           # 3
# 0    1451349050
# 1    1451347152
# 2    1451404752
# 3    1451462352
# 4    1451519952
# Name: orig, dtype: float64

df['fixed'] = pd.to_datetime(ts, unit='s')      # 4

print(df)

产量

                                    orig               fixed
0   (2015, 12, 29, 0, 30, 50, 1, 363, 0) 2015-12-29 00:30:50
1  (2015, 12, 28, 23, 59, 12, 0, 362, 0) 2015-12-28 23:59:12
2                                   None 2015-12-29 15:59:12
3                                        2015-12-30 07:59:12
4  (2015, 12, 30, 23, 59, 12, 0, 362, 0) 2015-12-30 23:59:12

<强>解释

  1. calendar.timegm将每个时间元组转换为时间戳。不像 time.mktime,它将时间元组解释为UTC,而不是当地时间。

  2. applytuple_to_timestamp的每一行调用df['orig']

  3. 关于时间戳的好处是它们是数字的,所以你可以使用它 数值方法,如Series.interpolate,用插值填充NaNs 值。请注意,两个NaN不会 填充相同的插值;它们的值根据ts.index给出的位置进行线性插值。

  4. pd.to_datetime将时间戳转换为日期。

答案 1 :(得分:2)

  1. 在pandas中处理日期和时间时,请使用pandas timestamp将其转换为pandas.to_datetime。要使用此功能,我们将列表转换为仅包含日期和时间元素的字符串。对于您的情况,不是长度为9的列表的值将被视为错误,并替换为空字符串''

    #convert list into string with date & time
    #only elements with lists of length 9 will be parsed
    dates_df = df_date_ugly.applymap(lambda x: "{0}/{1}/{2} {3}:{4}:{5}".format(x[0],x[1],x[2], x[3], x[4], x[5]) if len(x)==9 else '')
    
    #convert to a pandas timestamp
    dates_df = pd.to_datetime(dates_df['date'], errors = 'coerce'))
    
        date
    0   2015-12-29 00:30:50
    1   2015-12-28 23:59:12
    2   NaT
    3   NaT
    4   2015-12-28 23:59:12
    
  2. 使用pd.isnull()找到缺少日期的索引:

    >>>missing = pd.isnull(dates_df['date']).index
    >>>missing
    Int64Index([2, 3], dtype='int64')
    
  3. 将缺失日期设置为2个日期之间的中点:

    start_date = dates_df.iloc[0,:]
    end_date = dates_df.iloc[4,:]
    missing_date = start_date + (end_date - start_date)/2