【问题标题】:How to fill zeroes of a day with the previous day values in Pandas如何在 Pandas 中用前一天的值填充一天的零
【发布时间】:2020-06-12 01:39:24
【问题描述】:

我有几天完全为零,想用前一天的值替换它们,如下所示。

输入

       count
2020-02-01 00:00:00     12
2020-02-01 00:01:00     3
2020-02-01 00:02:00     14
2020-02-01 00:03:00     0
2020-02-01 00:04:00     22
2020-02-02 00:00:00     0
2020-02-02 00:01:00     0
2020-02-02 00:02:00     0
2020-02-02 00:03:00     0
2020-02-02 00:04:00     0
2020-02-03 00:00:00     2
2020-02-03 00:01:00     4
2020-02-03 00:02:00     1
2020-02-03 00:03:00     0
2020-02-03 00:04:00     22

输出

        count
2020-02-01 00:00:00     12
2020-02-01 00:01:00     3
2020-02-01 00:02:00     14
2020-02-01 00:03:00     0
2020-02-01 00:04:00     22
2020-02-02 00:00:00     12
2020-02-02 00:01:00     3
2020-02-02 00:02:00     14
2020-02-02 00:03:00     0
2020-02-02 00:04:00     22
2020-02-03 00:00:00     2
2020-02-03 00:01:00     4
2020-02-03 00:02:00     1
2020-02-03 00:03:00     0
2020-02-03 00:04:00     22

我正在尝试这样的事情,但无法解决。

df = df.fillna(0)
df = df.reset_index()

df['Date'] = df['index'].dt.date
df['Time'] = df['index'].dt.time


df.set_index(pd.to_datetime(df.Date + ' ' + df.Time), inplace=True)
for ind in df[df.count.eq(0)].index:
    df.loc[ind, 'count'] = df.loc[ind - pd.Timedelta('1D'), 'count']
df.reset_index(drop=True, inplace=True)

【问题讨论】:

  • 查看ffillbfill,它们应该用前一个值或下一个值填充缺失值。
  • 他们不考虑天数。它们只是填充以前或以后时间的值。
  • 您只想在当天全为 0 时填写?或者例如,如果您在第一天的小时 = 3 中有 1 而不是 0,那么您是否也会用 1 填充第 3 天的第 3 小时?
  • 好问题!我可以同时选择吗?

标签: python pandas


【解决方案1】:

您可以使用mask将0s替换为nan,然后groupby将DatetimeIndex中的时间和ffill替换为0,然后将fillna替换为0来完成之前没有值的时间。

df_ = (df.mask(df.eq(0))
         .groupby(df.index.time)
         .ffill() #add the parameter limit=1 if you want to fill only one day after
         .fillna(0)
      )
print (df_)
                     count
2020-02-01 00:00:00   12.0
2020-02-01 00:01:00    3.0
2020-02-01 00:02:00   14.0
2020-02-01 00:03:00    0.0
2020-02-01 00:04:00   22.0
2020-02-02 00:00:00   12.0
2020-02-02 00:01:00    3.0
2020-02-02 00:02:00   14.0
2020-02-02 00:03:00    0.0
2020-02-02 00:04:00   22.0
2020-02-03 00:00:00    2.0
2020-02-03 00:01:00    4.0
2020-02-03 00:02:00    1.0
2020-02-03 00:03:00    0.0
2020-02-03 00:04:00   22.0

如果您想在当天的所有值都为 0 的情况下填充以前的值,则在上面的 mask 中,将 df.eq(0) 更改为 df['count'].eq(0).groupby(df.index.date).transform('all')。在这种情况下,它不会改变结果。

如果你想填写同一时间到当前时间的平均值,那么你可以使用expanding like:

(df.mask(df.eq(0))
   .groupby(df.index.time)
   .expanding().mean()
   .fillna(0)
   .reset_index(level=0, drop=True).sort_index()
)

【讨论】:

  • 那行得通。哈哈。是否可以选择 X% 的日子是零而不是全零的日子?如果它很复杂,不需要回答:)。我已经占用了你很多时间。
  • @ferrelwill 在掩码中,您可以执行 (df['count'].eq(0) & df['count'].eq(0).groupby(df.index.day).transform('mean')>X) 其中 X 是 0 到 1 之间的数字
  • 我很困惑。这些值应该每分钟都不同,我想保持与前一个非零日相同的时间结构。例如:17 日下午 2 点,如果计数是 100,那么 18 日下午 2 点应该是相同的。每分钟都有不同的值,因此计数不应该是平的。希望这很清楚。
  • 同意,但 2 月 18 日的总和远低于 17 日。不应该一样吗?
  • 我看到输出没有时间戳。它只有一个日期。这就是为什么情节有一个平坦的趋势。是否可以在索引中同时包含日期和时间?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-02
  • 2021-12-13
  • 2022-07-08
  • 2021-07-20
  • 2020-07-30
相关资源
最近更新 更多