【问题标题】:Create new pandas timeseries dataframe from other dataframe从其他数据框创建新的熊猫时间序列数据框
【发布时间】:2015-01-17 04:35:23
【问题描述】:

如何从一个现有的 df 创建一个新的 pandas 时间序列数据框。

假设事件 A 开始于 11 月 28 日 11:35,结束于 11 月 29 日 19:53,这是计数 1。事件 A 的第二个实例再次开始于 11/28 11:37,结束于 11/29 19:53 - 又计数 1 . 所以我将 A 的值增加到 2。(对不起,数据输入错误的是 11/28 而不是 11/29)

源 df 给出了事件的开始和结束时间。并且同一事件可以同时发生多次。 新的 df 应具有给定分钟内事件累积计数的时间序列,范围从 Min(开始时间)到 Max(结束时间)。

来源 Df:

Start-Time       |  End-Time         | Event
11/28/2014 11:35 |  11/29/2014 19:53 | A
11/28/2014 11:36 |  11/28/2014 11:37 | B
11/28/2014 11:32 |  11/28/2014 19:53 | C
11/28/2014 11:37 |  11/28/2014 19:53 | A
......

新的 Df:

TimeStamp        | A |  B | C
11/28/2014 11:35 | 1 |  0 | 1
11/28/2014 11:36 | 1 |  1 | 1
11/28/2014 11:37 | 2 |  1 | 1
.....
11/29/2014 19:53 | 2 |  0 | 1

【问题讨论】:

  • 您是否想要在特定时间开始或结束的事件的累积计数?
  • 是的。假设事件 A 开始于 11/28 11:35 并结束于 11/29 19:53,这是计数 1。再次事件 A 2nd instance 开始于 11/28 11:37 并结束于 11/29 19:53 - 计数另一个 1。所以我将 A 的值增加到 2。(抱歉,数据输入错误地是 11/28 而不是 11/29)

标签: python pandas time-series


【解决方案1】:

这有点棘手,因为您希望结束时间算作“开启”状态,但我认为这样的事情应该可行(警告:我已经花了零时间考虑奇怪的边缘情况,所以买家要小心) :

df = pd.melt(df, id_vars="Event", var_name="Which", value_name="Time")
df["Signal"] = df.pop("Which").replace({"Start-Time": 1, "End-Time": -1})
pivoted = df.pivot(columns="Event", index="Time").fillna(0)
pivoted = pivoted.sort_index() # just in case; can't remember if this is guaranteed
df_out = pivoted.cumsum() + (pivoted == -1)

产生

>>> df_out
                 Signal      
Event                 A  B  C
Time                         
11/28/2014 11:32      0  0  1
11/28/2014 11:35      1  0  1
11/28/2014 11:36      1  1  1
11/28/2014 11:37      2  1  1
11/28/2014 19:53      2  0  1
11/29/2014 19:53      1  0  0

基本思想是添加一个签名的“信号”列并使用它来跟踪更改:

>>> df
  Event              Time  Signal
0     A  11/28/2014 11:35       1
1     B  11/28/2014 11:36       1
2     C  11/28/2014 11:32       1
3     A  11/28/2014 11:37       1
4     A  11/29/2014 19:53      -1
5     B  11/28/2014 11:37      -1
6     C  11/28/2014 19:53      -1
7     A  11/28/2014 19:53      -1

然后我们可以通过旋转来获取状态变化:

>>> pivoted
                 Signal      
Event                 A  B  C
Time                         
11/28/2014 11:32      0  0  1
11/28/2014 11:35      1  0  0
11/28/2014 11:36      0  1  0
11/28/2014 11:37      1 -1  0
11/28/2014 19:53     -1  0 -1
11/29/2014 19:53     -1  0  0

并累积得到状态:

>>> pivoted.cumsum()
                 Signal      
Event                 A  B  C
Time                         
11/28/2014 11:32      0  0  1
11/28/2014 11:35      1  0  1
11/28/2014 11:36      1  1  1
11/28/2014 11:37      2  0  1
11/28/2014 19:53      1  0  0
11/29/2014 19:53      0  0  0

这几乎是我们想要的,但您希望包含结束时间,因此我们可以通过撤消关闭来延迟效果:

>>> pivoted.cumsum() + (pivoted == -1)
                 Signal      
Event                 A  B  C
Time                         
11/28/2014 11:32      0  0  1
11/28/2014 11:35      1  0  1
11/28/2014 11:36      1  1  1
11/28/2014 11:37      2  1  1
11/28/2014 19:53      2  0  1
11/29/2014 19:53      1  0  0

【讨论】:

    【解决方案2】:

    这是一种与@DSM 略有不同的方法。我将start 和end 列堆叠在一起,然后在length 上使用groupby 和aggregate 函数进行过滤。然后为了达到所需的外观输出我pivot表。

    start = [35, 36, 37, 36, 35]
    end = [56, 56, 56, 58, 58]
    events = ['A', 'B', 'C', 'A', 'A']
    
    df = pd.DataFrame( {'start': start, 'end': end, 'events': events})
    
    # stack the 'start' and 'end' columns here
    new_df = pd.DataFrame({ 'times': df['start'].append(df['end']), 'events': df['events'].append(df['events']) })
    
    new_df = new_df.groupby(['times', 'events']).agg(len)
    
    # massage the data frame to conform to desired output
    new_df = new_df.reset_index().pivot('times', 'events').fillna(0)
    

    拼接后的数据框如下:

      events  times
    0      A     35
    1      B     36
    2      C     37
    3      A     36
    4      A     35
    0      A     56
    1      B     56
    2      C     56
    3      A     58
    4      A     58
    

    groupby分组后的数据框:

    times  events
    35     A         2
    36     A         1
           B         1
    37     C         1
    56     A         1
           B         1
           C         1
    58     A         2
    

    最后是枢轴后的数据框:

    events  A  B  C
    times          
    35      2  0  0
    36      1  1  0
    37      0  0  1
    56      1  1  1
    58      2  0  0
    

    我认为@DSM 的解决方案在计算时间方面比我的解决方案更有效,因为append 方法相当昂贵,因为它需要在每次调用时构造一个全新的对象。不过我还没有为这两种方法计时,所以我不确定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-14
      • 1970-01-01
      • 2019-12-09
      • 2019-06-16
      • 2020-09-21
      • 1970-01-01
      • 2016-08-28
      相关资源
      最近更新 更多