计算每组值的连续值和 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)
然后我计算了几个标识符:
- 每段的第一个元素 (first_stretch)
- 每段的最后一个元素 (last_stretch)
- 组拉伸(stretch_group)
- 与第一个值的时间差(timedelta)
- 连续行之间的时间差(time_diff)
- 每次拉伸中的累计时间(以秒为单位)(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
这些值并不严格相同,因此请说明您的时间间隔的确切范围。
我有一个 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)
然后我计算了几个标识符:
- 每段的第一个元素 (first_stretch)
- 每段的最后一个元素 (last_stretch)
- 组拉伸(stretch_group)
- 与第一个值的时间差(timedelta)
- 连续行之间的时间差(time_diff)
- 每次拉伸中的累计时间(以秒为单位)(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
这些值并不严格相同,因此请说明您的时间间隔的确切范围。