计算每组值的连续值和 average/min/max 时间

Count consecutive values and average/min/max time for each group of values

我有一个 pandas 数据框,其中包含一个日期时间索引以及多个 1 和 0 列。我希望将这些 1 和 0 聚集在一起,以计算出一个序列中有多少个。然后,我希望使用日期时间索引确定团块在每列中的最短时间、平均时间和最长时间。我只需要计算 1,因为本质上,在这种情况下它们是“开”值。如果只有一个1,那么从那个1到下一行的时间就是timeframe

到目前为止,我已经看到第一部分是这样完成的 post Counting cons values and adding them

y * (y.groupby((y != y.shift()).cumsum()).cumcount() + 1)

索引为“年-月-日hour:minute:second”

Dataframe的例子如下

                                   col1     col2
datetime
2021-05-24 00:09:22                    1       0 
2021-05-24 00:09:24                    1       0  
2021-05-24 00:09:25                    0       1 
2021-05-24 00:09:26                    1       0 
2021-05-24 00:09:27                    0       0

在几秒钟或几分钟内为列提供这样的所需输出。输出必须使用日期时间索引,而不是仅仅计算连续值并乘以时间,因为日期时间不一致。

col1              col2
min  1               1
max  3               1
mean 2               1

你可以试试这个:

def count_secs(ser):
    return (ser.index[-1] - ser.index[0]).seconds + 1

def min_max_mean(col):
    if 1 not in col.values:
        return 0, 0, 0
    groups = (col != col.shift(1))[col.eq(1)].cumsum()
    counts = groups.groupby(groups.values).apply(count_secs)
    return counts.min(), counts.max(), counts.mean()

df = df.apply(min_max_mean, axis='index')
df.index = ['min', 'max', 'mean']

df

的结果
                     col1  col2
datetime                       
2021-05-24 00:09:22     1     0
2021-05-24 00:09:24     1     0
2021-05-24 00:09:25     0     1
2021-05-24 00:09:26     1     0
2021-05-24 00:09:27     0     0

      col1  col2
min    1.0   1.0
max    3.0   1.0
mean   2.0   1.0

编辑:我对你的问题的解释是你想考虑索引中丢失的秒数(你的示例输出表明这就是你要找的) .如果不是这种情况 - 请参阅@mozway 的回答 - 那么没有 count_secs 函数的更简单版本就足够了:

def min_max_mean(col):
    if 1 not in col.values:
        return 0, 0, 0
    groups = (col != col.shift(1))[col.eq(1)].cumsum()
    counts = groups.groupby(groups.values).count()
    return counts.min(), counts.max(), counts.mean()

df = df.apply(min_max_mean, axis='index')
df.index = ['min', 'max', 'mean']

结果:

      col1  col2
min    1.0   1.0
max    2.0   1.0
mean   1.5   1.0

我不太清楚你想要的确切操作,但如果我正确理解你想要统计 1 的持续时间,你可以使用以下方法:

首先,确保索引使用日期时间类型:

df.index = pd.to_datetime(df.index)

然后我计算了几个标识符:

  1. 每段的第一个元素 (first_stretch)
  2. 每段的最后一个元素 (last_stretch)
  3. 组拉伸(stretch_group)
  4. 与第一个值的时间差(timedelta)
  5. 连续行之间的时间差(time_diff)
  6. 每次拉伸中的累计时间(以秒为单位)(cum_diff)
df['first_stretch'] = df['col1']&df['col1'].shift(1).fillna(0).eq(0)
df['last_stretch']  = (df['col1']-df['col1'].shift(-1)).eq(1)
df['stretch_group'] = df['first_stretch'].cumsum().mask(~df['col1'].astype(bool))
df['timedelta'] = (df.index-df.index[0]).total_seconds().astype(int)
df['timediff'] = df['timedelta'].diff(1).fillna(0).astype(int)
df['cum_diff'] = df.groupby('stretch_group')['timediff'].cumsum()*df['col1']

                     col1  col2  first_stretch  last_stretch  stretch_group  timedelta  timediff  cum_diff
datetime                                                                                                  
2021-05-24 00:09:22     1     0           True         False            1.0          0         0         0
2021-05-24 00:09:24     1     0          False          True            1.0          2         2         2
2021-05-24 00:09:25     0     1          False         False            NaN          3         1         0
2021-05-24 00:09:26     1     0           True          True            2.0          4         1         1
2021-05-24 00:09:27     0     0          False         False            NaN          5         1         0

也许您不需要所有这些,但这可以让您轻松进行各种计算。例如,如果您想获得每个伸展的 min/max/mean 持续时间:

>>> df[df.last_stretch]['timediff'].agg(['mean', 'min', 'max'])
mean    1.5
min     1.0
max     2.0

这些值并不严格相同,因此请说明您的时间间隔的确切范围。