将 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 &lt; 5].diff().fillna(df) 应该这样做。 仅当缺少的日期在工作日时。如果错过的日期是周末,则需要滚动到下一个工作日。 我什至没有想到周末什么时候结束。嗯,我得更新我的答案了。

以上是关于将 pandas 数据框中的一些行添加到下一个,然后删除它们的主要内容,如果未能解决你的问题,请参考以下文章

如何检测表视图中的项目何时更改?

如果值在列表中,则 Pandas 数据框中的重复行

如何将命名向量作为行添加到数据框中,根据列名顺序重新排序?

使用 R 中的多参数用户定义函数将列添加到数据框中

对 Spark 数据框中的行进行洗牌

如何将当前行的负值转移到数据框中的前一行?