【问题标题】:Pandas Reindex to Fill Missing Dates, or Better Method to Fill?Pandas 重新索引以填充缺失的日期,还是更好的填充方法?
【发布时间】:2018-01-12 08:20:02
【问题描述】:

我的数据是工厂的缺勤记录。有些日子没有缺勤,因此没有记录当天的数据或日期。但是,在显示的其他示例中,这变得很棘手,在任何一天,都可能由于各种原因而缺席几次。数据中的日期与记录的比率并不总是 1 比 1。

我希望的结果是这样的:

(index)    Shift        Description     Instances (SUM)
01-01-14   2nd Baker    Discipline      0
01-01-14   2nd Baker    Vacation        0
01-01-14   1st Cooks    Discipline      0
01-01-14   1st Cooks    Vacation        0
01-02-14   2nd Baker    Discipline      4
01-02-14   2nd Baker    Vacation        3
01-02-14   1st Cooks    Discipline      3
01-02-14   1st Cooks    Vacation        3

等等。这个想法是所有班次和描述都将具有该时间段内所有日期的值(在此示例中为 2014 年 1 月 1 日 - 2014 年 12 月 31 日)

我已经阅读了几个例子,我最接近这个工作的是here

ts = pd.read_csv('Absentee_Data_2.csv'
                , encoding = 'utf-8'
                ,parse_dates=[3]
                ,index_col=3
                ,dayfirst=True
                )

idx =  pd.date_range('01.01.2009', '12.31.2017')

ts.index = pd.DatetimeIndex(ts.index)
# ts = ts.reindex(idx, fill_value='NaN')
df = pd.DataFrame(index = idx)
df1 = df.join(ts, how='left')

但是,当我取消注释 ts = ts.reindex(idx, fill_value='NaN') 时,我会收到错误消息。我已经尝试了至少 10 种其他方法来完成我正在尝试做的事情,所以我不能 100% 确定这是正确的道路,但它似乎让我最接近任何进展。

以下是一些示例数据:

Description Unexcused   Instances   Date        Shift
Discipline  FALSE              1    Jan 2 2014  2nd Baker
Vacation    TRUE               2    Jan 2 2014  1st Cooks
Discipline  FALSE              3    Jan 2 2014  2nd Baker
Vacation    TRUE               1    Jan 2 2014  1st Cooks
Discipline  FALSE              2    Apr 8 2014  2nd Baker
Vacation    TRUE               3    Apr 8 2014  1st Cooks
Discipline  FALSE              1    Jun 1 2014  2nd Baker
Vacation    TRUE               2    Jun 1 2014  1st Cooks
Discipline  FALSE              3    Jun 1 2014  2nd Baker
Vacation    TRUE               1    Jun 1 2014  1st Cooks
Vacation    TRUE               2    Jul 5 2014  1st Cooks
Discipline  FALSE              3    Jul 5 2014  2nd Baker
Vacation    TRUE               2    Dec 3 2014  1st Cooks

提前感谢您的帮助,我是新手,2 天后没有太大进展。我非常感谢这里的人们如何帮助解答问题,但最重要的是说明解决方案为何有效。像我这样的新手非常感谢分享的智慧。

【问题讨论】:

    标签: python python-3.x pandas pandas-groupby


    【解决方案1】:

    我认为您只是在使用日期时间方面遇到了问题,这种方法对我有用

    ts.set_index(['Date'],inplace=True)
    ts.index = pd.to_datetime(ts.index,format='%b %d %Y')
    d2 = pd.DataFrame(index=pd.date_range('2014-01-01','2014-12-31'))
    
    print ts.join(d2,how='right')
    

    【讨论】:

    • 两个答案都有效,但这个答案更容易让我理解并循环使用我的真实数据。我确实需要做一些进一步的操作和思考,但这最终是我使用的答案。
    • 也为我工作!我有一个 900,000 行的“smeidum”数据框,并希望在数据透视之前添加缺失的日期。谢谢!
    【解决方案2】:

    实际上,您已经非常接近您想要的(假设我正确理解了您似乎正在寻找的输出)。请参阅我在上面的代码中添加的内容:

    import pandas as pd
    
    ts = pd.read_csv('Absentee_Data_2.csv', encoding = 'utf-8',parse_dates=[3],index_col=3,dayfirst=True, sep=",")
    
    idx =  pd.date_range('01.01.2009', '12.31.2017')
    
    ts.index = pd.DatetimeIndex(ts.index)
    #ts = ts.reindex(idx, fill_value='NaN')
    df = pd.DataFrame(index = idx)
    df1 = df.join(ts, how='left')
    df2 = df1.copy()
    df3 = df1.copy()
    df4 = df1.copy()
    dict1 = {'Description': 'Discipline', 'Instances': 0, 'Shift': '1st Cooks'}
    df1 = df1.fillna(dict1)
    dict1["Description"] = "Vacation"
    df2 = df2.fillna(dict1)
    dict1["Shift"] = "2nd Baker"
    df3 = df3.fillna(dict1)
    dict1["Description"] = "Discipline"
    df4 = df4.fillna(dict1)
    df_with_duplicates = pd.concat([df1,df2,df3,df4])
    final_res = df_with_duplicates.reset_index().drop_duplicates(subset=["index"] + list(dict1.keys())).set_index("index").drop("Unexcused", axis=1)
    

    基本上你要添加的内容:

    • 将使用 ts (df1) 创建的几乎为空的 df 复制 4 次
    • fillna(dict1) 允许用静态值填充列中的所有 NaN
    • 连接 4 个 dfs,我们仍然需要删除一些重复项,因为 csv 中的原始值重复了 4 次
    • 删除重复项,我们需要索引来保留添加的值,因此 reset_index 后跟 `set_index("index")
    • 最后删除 Unexcused

    最后几个输出:

    In [5]: final_res["2013-01-2"]
    Out[5]: 
               Description  Instances      Shift
    index                                       
    2013-01-02  Discipline        0.0  1st Cooks
    2013-01-02    Vacation        0.0  1st Cooks
    2013-01-02    Vacation        0.0  2nd Baker
    2013-01-02  Discipline        0.0  2nd Baker
    
    In [6]: final_res["2014-01-2"]
    Out[6]: 
               Description  Instances       Shift
    index                                        
    2014-01-02  Discipline        1.0   2nd Baker
    2014-01-02    Vacation        2.0   1st Cooks
    2014-01-02  Discipline        3.0   2nd Baker
    2014-01-02    Vacation        1.0   1st Cooks
    1
    

    【讨论】:

    • 尝试此解决方案,但我不断收到以下错误:“类型错误:只能将列表(不是“dict_keys”)连接到以下代码行:“final_res = (df_with_duplicates.reset_index () .drop_duplicates(subset=["index"] + dict1.keys()) .set_index("index").drop("Unexcused", axis=1))" 有什么建议吗?谢谢你,也谢谢你的解释:)
    • @SDS 我错了一个小错字,您需要将dict1 的键转换为列表,所以应该是subse‌​t=["index"] + list(dict1.keys()),我编辑了我的帖子
    • @SDS 如果您认为已提供答案,请将其标记为已接受。它有助于将注意力集中在未回答的问题上。如果答案没有帮助,您能否就缺少的内容提供反馈?
    猜你喜欢
    • 2017-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 2021-09-03
    相关资源
    最近更新 更多