Fillna 一次使用多种方法 - pandas
Posted
技术标签:
【中文标题】Fillna 一次使用多种方法 - pandas【英文标题】:Fillna using multiple approaches at a time - pandas 【发布时间】:2021-07-06 17:41:21 【问题描述】:我有一个如下所示的数据框
df = pd.DataFrame('person_id': [101,101,101,101,202,202,202],
'start_date':['5/7/2013 09:27:00 AM','09/08/2013 11:21:00 AM','06/06/2014 08:00:00 AM','06/06/2014 05:00:00 AM','12/11/2011 10:00:00 AM','13/10/2012 12:00:00 AM','13/12/2012 11:45:00 AM'],
'end_date':['5/12/2013 09:27:00 AM',np.nan,'06/11/2014 08:00:00 AM',np.nan,'12/16/2011 10:00:00','10/18/2012 00:00:00',np.nan],
'type':['O','I','O','O','I','O','I'])
df.start_date = pd.to_datetime(df.start_date)
df['end_date'] = pd.to_datetime(df.end_date)
我想根据以下两种方法在end_date
列下fillna()
a) 如果在该人的除最后一行之外的任何行中找到NA
,则通过复制下一行的值来fillna
b) 如果在 该人的最后一行 fillna
中找到NA
,则在他的start_date
上添加 10 天(因为该人没有下一行可供复制. 所以,我们给出 10 天的随机值)
规则a
和b
仅适用于type=I
的人。
对于具有type=O
的人,只需复制start_date
中的值即可。
这是我尝试过的。你可以看到我写了两次相同的代码行。
df['end_date'] = np.where(df['type'].str.contains('I'),pd.DatetimeIndex(df['end_date'].bfill()),pd.DatetimeIndex(df.start_date.dt.date))
df['end_date'] = np.where(df['type'].str.contains('I'),pd.DatetimeIndex(df['start_date'] + pd.DateOffset(10)),pd.DatetimeIndex(df.start_date.dt.date))
任何优雅而有效的方式来编写这个,因为我必须将它应用到一个有 1500 万行的大数据上?
我希望我的输出如下所示
【问题讨论】:
您的预期输出似乎不正确。请再次检查并相应地更新预期输出。谢谢。 如果在除该人的最后一行之外的任何行中找到 NA,则通过复制下一行的值来填充您是指来自 @987654337@ 的下一行还是start_date
专栏?
该特定人员的start_date
列的下一行。不是来自其他 person_ids。
更新了预期的输出
@ShubhamSharma - 顺便说一句,几周前你帮我解决了一个问题。但是忘记写答案了。如果您也可以为旧问题写一个答案(我相信它会在我们的聊天窗口中,我无法访问),我可以投票并接受它。
【参考方案1】:
解决方案
s1 = df.groupby('person_id')['start_date'].shift(-1)
s1 = s1.fillna(df['start_date'] + pd.DateOffset(days=10))
s1 = df['end_date'].fillna(s1)
s2 = df['end_date'].fillna(df['start_date'])
df['end_date'] = np.where(df['type'].eq('I'), s1, s2)
说明
Group
person_id
和 shift
列上的数据框 start_date
向上一个单位。
>>> df.groupby('person_id')['start_date'].shift(-1)
0 2013-09-08 11:21:00
1 2014-06-06 08:00:00
2 2014-06-06 05:00:00
3 NaT
4 2012-10-13 00:00:00
5 2012-12-13 11:45:00
6 NaT
Name: start_date, dtype: datetime64[ns]
添加10 days
的偏移量后,用start_date
列中的值填充移位列中的NaN
值
>>> s1.fillna(df['start_date'] + pd.DateOffset(days=10))
0 2013-09-08 11:21:00
1 2014-06-06 08:00:00
2 2014-06-06 05:00:00
3 2014-06-16 05:00:00
4 2012-10-13 00:00:00
5 2012-12-13 11:45:00
6 2012-12-23 11:45:00
Name: start_date, dtype: datetime64[ns]
现在用上述系列s1
填充end_date
列中的NaN
值
>>> df['end_date'].fillna(s1)
0 2013-05-12 09:27:00
1 2014-06-06 08:00:00
2 2014-06-11 08:00:00
3 2014-06-16 05:00:00
4 2011-12-16 10:00:00
5 2012-10-18 00:00:00
6 2012-12-23 11:45:00
Name: end_date, dtype: datetime64[ns]
类似地用start_date
列中的值填充end_date
列中的NaN
值以创建系列s2
>>> df['end_date'].fillna(df['start_date'])
0 2013-05-12 09:27:00
1 2013-09-08 11:21:00
2 2014-06-11 08:00:00
3 2014-06-06 05:00:00
4 2011-12-16 10:00:00
5 2012-10-18 00:00:00
6 2012-12-13 11:45:00
Name: end_date, dtype: datetime64[ns]
然后根据类型为I
或O
的条件,使用np.where
从s1
/s2
中选择值
>>> df
person_id start_date end_date type
0 101 2013-05-07 09:27:00 2013-05-12 09:27:00 O
1 101 2013-09-08 11:21:00 2014-06-06 08:00:00 I
2 101 2014-06-06 08:00:00 2014-06-11 08:00:00 O
3 101 2014-06-06 05:00:00 2014-06-06 05:00:00 O
4 202 2011-12-11 10:00:00 2011-12-16 10:00:00 I
5 202 2012-10-13 00:00:00 2012-10-18 00:00:00 O
6 202 2012-12-13 11:45:00 2012-12-23 11:45:00 I
【讨论】:
以上是关于Fillna 一次使用多种方法 - pandas的主要内容,如果未能解决你的问题,请参考以下文章
python - Pandas - FillNa 与另一个具有相似列的非空行
有没有更好的方法来对大熊猫使用'ffill'方法进行分段的fillna?
如何在 pandas fillna() 方法中为不同的列应用不同的方法参数
Pandas:具有多索引的 fillna() 方法 - NaN 填充了错误的列