【问题标题】:How Can I Detect Gaps and Consecutive Periods In A Time Series In Pandas如何在 Pandas 的时间序列中检测间隙和连续周期
【发布时间】:2017-02-28 07:19:57
【问题描述】:

我有一个按日期索引的熊猫数据框。我想按周期选择所有连续的间隔,按周期选择所有连续的天。我该怎么做?

没有列但有日期索引的数据框示例:

In [29]: import pandas as pd

In [30]: dates = pd.to_datetime(['2016-09-19 10:23:03', '2016-08-03 10:53:39','2016-09-05 11:11:30', '2016-09-05 11:10:46','2016-09-05 10:53:39'])

In [31]: ts = pd.DataFrame(index=dates)

如您所见,2016 年 8 月 3 日和 2016 年 9 月 19 日之间存在 差距。如何检测这些,以便创建描述性统计数据,即 40 个间隙,中间间隙持续时间为“x”等。此外,我可以看到 2016-09-05 和 2016-09-06 是两个日期范围。我如何检测这些并打印描述性统计信息?

理想情况下,在每种情况下,结果都将作为另一个 Dataframe 返回,因为我想使用 Dataframe 中的其他列来分组。

【问题讨论】:

标签: python pandas


【解决方案1】:

这里有一些东西可以开始:

df = pd.DataFrame(np.ones(5),columns = ['ones'])
df.index = pd.DatetimeIndex(['2016-09-19 10:23:03', '2016-08-03 10:53:39', '2016-09-05 11:11:30', '2016-09-05 11:10:46', '2016-09-06 10:53:39'])
daily_rng = pd.date_range('2016-08-03 00:00:00', periods=48, freq='D')
daily_rng = daily_rng.append(df.index)
daily_rng = sorted(daily_rng)
df =  df.reindex(daily_rng).fillna(0)
df = df.astype(int)
df['ones'] = df.cumsum()

cumsum() 在“ones”上创建一个分组变量,在您提供的点对您的数据进行分区。如果您打印 df 来表示电子表格,那将是有意义的:

print df.head()

                     ones
2016-08-03 00:00:00     0
2016-08-03 10:53:39     1
2016-08-04 00:00:00     1
2016-08-05 00:00:00     1
2016-08-06 00:00:00     1

print df.tail()
                     ones
2016-09-16 00:00:00     4
2016-09-17 00:00:00     4
2016-09-18 00:00:00     4
2016-09-19 00:00:00     4
2016-09-19 10:23:03     5

现在完成:

df = df.reset_index()
df = df.groupby(['ones']).aggregate({'ones':{'gaps':'count'},'index':{'first_spotted':'min'}})
df.columns = df.columns.droplevel()

给出:

              first_time  gaps
ones                          
0    2016-08-03 00:00:00     1
1    2016-08-03 10:53:39    34
2    2016-09-05 11:10:46     1
3    2016-09-05 11:11:30     2
4    2016-09-06 10:53:39    14
5    2016-09-19 10:23:03     1

【讨论】:

  • 这看起来是一个好的开始。我在cumsum之后迷路了。此时:In [11]: df = df.astype(int) In [12]: df.head() Out[12]: ones 2016-08-03 00:00:00 0 2016-08-03 10:53:39 1 2016-08-04 00:00:00 0 2016-08-05 00:00:00 0 2016-08-06 00:00:00 0
  • 关键步骤是得到一个分组变量,这就是 cumsum 的用途。
  • 您能解释一下我将如何采用该分组变量并检测第一个间隙和第一个连续条纹吗?
  • 到目前为止的解决方案是否正确显示了差距?我们可以稍后解决连续的条纹。
  • 你几乎可以把差距标记为“差距”,然后我会给你答案。
【解决方案2】:

Pandas 1.0.1 版有一个内置方法DataFrame.diff(),您可以使用它来完成此操作。一个好处是您可以使用像 mean() 这样的 pandas 系列函数来快速计算 gaps 系列对象的汇总统计信息

from datetime import datetime, timedelta
import pandas as pd

# Construct dummy dataframe
dates = pd.to_datetime([
    '2016-08-03',
    '2016-08-04',
    '2016-08-05',
    '2016-08-17',
    '2016-09-05',
    '2016-09-06',
    '2016-09-07',
    '2016-09-19'])
df = pd.DataFrame(dates, columns=['date'])

# Take the diff of the first column (drop 1st row since it's undefined)
deltas = df['date'].diff()[1:]

# Filter diffs (here days > 1, but could be seconds, hours, etc)
gaps = deltas[deltas > timedelta(days=1)]

# Print results
print(f'{len(gaps)} gaps with average gap duration: {gaps.mean()}')
for i, g in gaps.iteritems():
    gap_start = df['date'][i - 1]
    print(f'Start: {datetime.strftime(gap_start, "%Y-%m-%d")} | '
          f'Duration: {str(g.to_pytimedelta())}')

【讨论】:

  • 如果我使用“日期”列作为 df 中的索引,如何估计增量?函数 pd.index.difference() 确实有所不同。
猜你喜欢
  • 2021-07-23
  • 1970-01-01
  • 2019-05-16
  • 1970-01-01
  • 2016-05-07
  • 2016-11-29
  • 2015-02-25
  • 2019-03-27
  • 1970-01-01
相关资源
最近更新 更多