Pandas 重建索引以填充缺失日期,还是更好的填充方法?
Pandas Reindex to Fill Missing Dates, or Better Method to Fill?
我的数据是工厂的缺勤记录。有些日子没有缺勤,因此没有记录当天的数据或日期。然而,在显示的其他示例中,这变得毛茸茸的地方是,在任何给定的一天,由于各种原因可能会有几次缺席。数据中的日期与记录的比例并不总是 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 日)
我已经阅读了几个例子,我最接近这个工作的是 。
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 天了,但没有太大进展。我真的很感谢这里的人们如何帮助解决问题,但最重要的是指导解决方案为何有效。像我这样的新手非常感谢分享的智慧。
我认为你只是对日期时间的使用有问题,这个方法对我有用
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')
实际上你已经非常接近你想要的了(假设我正确理解了你似乎正在寻找的输出)。请参阅我在上面的代码中添加的内容:
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 个 df,我们仍然需要删除一些重复项,因为 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
我的数据是工厂的缺勤记录。有些日子没有缺勤,因此没有记录当天的数据或日期。然而,在显示的其他示例中,这变得毛茸茸的地方是,在任何给定的一天,由于各种原因可能会有几次缺席。数据中的日期与记录的比例并不总是 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 日)
我已经阅读了几个例子,我最接近这个工作的是
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 天了,但没有太大进展。我真的很感谢这里的人们如何帮助解决问题,但最重要的是指导解决方案为何有效。像我这样的新手非常感谢分享的智慧。
我认为你只是对日期时间的使用有问题,这个方法对我有用
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')
实际上你已经非常接近你想要的了(假设我正确理解了你似乎正在寻找的输出)。请参阅我在上面的代码中添加的内容:
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 个 df,我们仍然需要删除一些重复项,因为 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