将 pandas 数据框中的一些行添加到下一个,然后删除它们
Posted
技术标签:
【中文标题】将 pandas 数据框中的一些行添加到下一个,然后删除它们【英文标题】:Add some rows from pandas dataframe to next, then remove them 【发布时间】:2019-01-14 21:00:27 【问题描述】:我有一个包含很多列的 pandas 数据框,其中一些列在周末有值。
我现在正在尝试删除所有周末行,但需要将我删除的值添加到相应的下周一。
Thu: 4
Fri: 5
Sat: 2
Sun: 1
Mon: 4
Tue: 3
需要成为
Thu: 4
Fri: 5
Mon: 7
Tue: 3
我已经想出了如何只对工作日进行切片(使用 df.index.dayofweek),但在这样做之前想不出一个聪明的方法来聚合。
下面是一些虚拟代码:
index = pd.date_range(datetime.datetime.now().date() -
datetime.timedelta(20),
periods = 20,
freq = 'D')
df = pd.DataFrame(
'Val_1': np.random.rand(20),
'Val_2': np.random.rand(20),
'Val_3': np.random.rand(20)
,
index = index)
df['Weekday'] = df.index.dayofweek
对此的任何帮助将不胜感激!
【问题讨论】:
【参考方案1】:设置
我包含了一个随机种子
np.random.seed([3, 1415])
index = pd.date_range(datetime.datetime.now().date() -
datetime.timedelta(20),
periods = 20,
freq = 'D')
df = pd.DataFrame(
'Val_1': np.random.rand(20),
'Val_2': np.random.rand(20),
'Val_3': np.random.rand(20)
,
index = index)
df['day_name'] = df.index.day_name()
df.head(6)
Val_1 Val_2 Val_3 day_name
2018-07-18 0.444939 0.278735 0.651676 Wednesday
2018-07-19 0.407554 0.609862 0.136097 Thursday
2018-07-20 0.460148 0.085823 0.544838 Friday
2018-07-21 0.465239 0.836997 0.035073 Saturday
2018-07-22 0.462691 0.739635 0.275079 Sunday
2018-07-23 0.016545 0.866059 0.706685 Monday
解决方案
我在周六和周日的下周一填写一系列日期。这会按操作分组使用。
weekdays = df.index.to_series().mask(df.index.dayofweek >= 5).bfill()
d_ = df.groupby(weekdays).sum()
d_
Val_1 Val_2 Val_3
2018-07-18 0.444939 0.278735 0.651676
2018-07-19 0.407554 0.609862 0.136097
2018-07-20 0.460148 0.085823 0.544838
2018-07-23 0.944475 2.442691 1.016837
2018-07-24 0.850445 0.691271 0.713614
2018-07-25 0.817744 0.377185 0.776050
2018-07-26 0.777962 0.225146 0.542329
2018-07-27 0.757983 0.435280 0.836541
2018-07-30 2.645824 2.198333 1.375860
2018-07-31 0.926879 0.018688 0.746060
2018-08-01 0.721535 0.700566 0.373741
2018-08-02 0.117642 0.900749 0.603536
2018-08-03 0.145906 0.764869 0.775801
2018-08-06 0.738110 1.580137 1.266593
比较
df.join(d_, rsuffix='_')
Val_1 Val_2 Val_3 day_name Val_1_ Val_2_ Val_3_
2018-07-18 0.444939 0.278735 0.651676 Wednesday 0.444939 0.278735 0.651676
2018-07-19 0.407554 0.609862 0.136097 Thursday 0.407554 0.609862 0.136097
2018-07-20 0.460148 0.085823 0.544838 Friday 0.460148 0.085823 0.544838
2018-07-21 0.465239 0.836997 0.035073 Saturday NaN NaN NaN
2018-07-22 0.462691 0.739635 0.275079 Sunday NaN NaN NaN
2018-07-23 0.016545 0.866059 0.706685 Monday 0.944475 2.442691 1.016837
2018-07-24 0.850445 0.691271 0.713614 Tuesday 0.850445 0.691271 0.713614
2018-07-25 0.817744 0.377185 0.776050 Wednesday 0.817744 0.377185 0.776050
2018-07-26 0.777962 0.225146 0.542329 Thursday 0.777962 0.225146 0.542329
2018-07-27 0.757983 0.435280 0.836541 Friday 0.757983 0.435280 0.836541
2018-07-28 0.934829 0.700900 0.538186 Saturday NaN NaN NaN
2018-07-29 0.831104 0.700946 0.185523 Sunday NaN NaN NaN
2018-07-30 0.879891 0.796487 0.652151 Monday 2.645824 2.198333 1.375860
2018-07-31 0.926879 0.018688 0.746060 Tuesday 0.926879 0.018688 0.746060
2018-08-01 0.721535 0.700566 0.373741 Wednesday 0.721535 0.700566 0.373741
2018-08-02 0.117642 0.900749 0.603536 Thursday 0.117642 0.900749 0.603536
2018-08-03 0.145906 0.764869 0.775801 Friday 0.145906 0.764869 0.775801
2018-08-04 0.199844 0.253200 0.091238 Saturday NaN NaN NaN
2018-08-05 0.437564 0.548054 0.504035 Sunday NaN NaN NaN
2018-08-06 0.100702 0.778883 0.671320 Monday 0.738110 1.580137 1.266593
【讨论】:
非常感谢大家!!【参考方案2】:使用简单的系列设置数据,以便周末滚动值显而易见:
index = pd.date_range(start='2018-07-18', periods = 20, freq = 'D')
df = pd.DataFrame(
'Val_1': [1] * 20,
'Val_2': [2] * 20,
'Val_3': [3] * 20,
,
index = index)
您可以获取数据框中相关列的累积总和,然后使用工作日布尔过滤器区分结果。您需要应用一些特殊的逻辑来正确计算第一天,具体取决于它是工作日、星期六还是星期日。
可以使用 7 月 21 日(星期六)和 22 日(星期日)的索引开始日期来观察正确的滚动行为。
此外,您可能需要考虑最后一两天是周末的情况。照原样,这些值将丢失。根据情况,您可能希望将它们前滚到下一个星期一(在这种情况下,您需要扩展索引)或者将它们回滚到前一个星期五。
weekdays = df.index.dayofweek < 5
df2 = df.iloc[:, :].cumsum()[weekdays].diff()
if weekdays[0]:
# First day is a weekday, so just use its value.
df2.iloc[0, :] = df.iloc[0, :]
elif weekdays[1]:
# First day must be a Sunday.
df2.iloc[0, :] = df.iloc[0:2, :].sum()
else:
# First day must be a Saturday.
df2.iloc[0, :] = df.iloc[0:3, :].sum()
>>> df2.head(14)
Val_1 Val_2 Val_3
2018-07-18 1 2 3
2018-07-19 1 2 3
2018-07-20 1 2 3
2018-07-23 3 6 9
2018-07-24 1 2 3
2018-07-25 1 2 3
2018-07-26 1 2 3
2018-07-27 1 2 3
2018-07-30 3 6 9
2018-07-31 1 2 3
2018-08-01 1 2 3
2018-08-02 1 2 3
2018-08-03 1 2 3
2018-08-06 3 6 9
【讨论】:
这也很聪明。df.iloc[:, :3].cumsum()[df.index.weekday < 5].diff().fillna(df)
应该这样做。
仅当缺少的日期在工作日时。如果错过的日期是周末,则需要滚动到下一个工作日。
我什至没有想到周末什么时候结束。嗯,我得更新我的答案了。以上是关于将 pandas 数据框中的一些行添加到下一个,然后删除它们的主要内容,如果未能解决你的问题,请参考以下文章