Python 有没有更快的方法来查找数据帧中常量值的范围?

Python 有没有更快的方法来查找数据帧中常量值的范围?,python,pandas,dataframe,datetime,Python,Pandas,Dataframe,Datetime,我想找出数据帧中常量值的最长持续时间。例如,给定下面的数据帧,最长持续时间应为30分钟(当值=2时) (注意:日期和时间间隔并不总是一致的。) 我通过查找df.value.diff().abs()==0的索引找到了它,构建了一个复杂的函数来迭代该列表并计算范围 由于实际的数据帧比这个示例大得多,是否有一个快捷函数或一种更快的方法来获得它而无需多次迭代 多谢各位 编辑: 在我的例子中,相同的值可以出现在其他条纹中。一个更合适的例子是 d = {'date_time': ['2016-01-01 1

我想找出数据帧中常量值的最长持续时间。例如,给定下面的数据帧,最长持续时间应为30分钟(当值=2时)

(注意:日期和时间间隔并不总是一致的。)

我通过查找
df.value.diff().abs()==0
的索引找到了它,构建了一个复杂的函数来迭代该列表并计算范围

由于实际的数据帧比这个示例大得多,是否有一个快捷函数或一种更快的方法来获得它而无需多次迭代

多谢各位

编辑:

在我的例子中,相同的值可以出现在其他条纹中。一个更合适的例子是

d = {'date_time': ['2016-01-01 12:00:00', '2016-01-01 12:15:00',
       '2016-01-01 12:30:00', '2016-01-01 12:45:00',
       '2016-01-01 13:00:00', '2016-01-01 13:15:00',
       '2016-01-01 13:30:00', '2016-01-01 13:45:00',
       '2016-01-01 14:00:00', '2016-01-01 14:05:00'], 
     'value': [1,2,2,2,4,5,5,7,5,5]}

df = pd.DataFrame(data=d)

df['date_time'] = pd.to_datetime(df['date_time'])

print(df)

            date_time  value
0 2016-01-01 12:00:00      1
1 2016-01-01 12:15:00      2
2 2016-01-01 12:30:00      2
3 2016-01-01 12:45:00      2
4 2016-01-01 13:00:00      4
5 2016-01-01 13:15:00      5
6 2016-01-01 13:30:00      5
7 2016-01-01 13:45:00      7
8 2016-01-01 14:00:00      5
9 2016-01-01 14:05:00      5

在这种情况下,当value=2时,最长持续时间为30分钟。

您可以按value列分组,并使用
.size()
获取每组的大小/长度

import pandas as pd

d = {'date_time': ['2016-01-01 12:00:00', '2016-01-01 12:15:00',
       '2016-01-01 12:30:00', '2016-01-01 12:45:00',
       '2016-01-01 13:00:00', '2016-01-01 13:15:00',
       '2016-01-01 13:30:00', '2016-01-01 13:45:00'], 
     'value': [1,2,2,2,4,5,5,7]}

df = pd.DataFrame(data=d)

df['date_time'] = pd.to_datetime(df['date_time'])

print(df)
            date_time  value
0 2016-01-01 12:00:00      1
1 2016-01-01 12:15:00      2
2 2016-01-01 12:30:00      2
3 2016-01-01 12:45:00      2
4 2016-01-01 13:00:00      4
5 2016-01-01 13:15:00      5
6 2016-01-01 13:30:00      5
7 2016-01-01 13:45:00      7
>>> groups = df.groupby('value')
>>> groups.size()
value
1    1
2    3
4    1
5    2
7    1
dtype: int64
.idxmax()
将为您提供可以传递到
的最大组的索引。get_groups()

然后,您可以区分最后一个日期和第一个日期(假设它们已排序-如果未排序,则可以排序)

如果
value
可以在其他条纹中重复,则可以使用以下方法进行分组:

groups = df.groupby((df.value != df.value.shift()).cumsum())
更新:任何条纹的最大持续时间

>>> groups = df.groupby((df.value != df.value.shift()).cumsum())
>>> last = groups.last()
>>> max_duration = (last.date_time - groups.first().date_time).nlargest(1)
>>> max_duration.iat[0]
Timedelta('0 days 00:30:00')
>>> last.loc[max_duration.index].value.iat[0]
2

您可以使用pd.pivot_表获取每个值的最小和最大日期时间值,然后计算它们之间的持续时间并提取最长的时间

import pandas as pd
import numpy as np

d = {'date_time': ['2016-01-01 12:00:00', '2016-01-01 12:15:00',
       '2016-01-01 12:30:00', '2016-01-01 12:45:00',
       '2016-01-01 13:00:00', '2016-01-01 13:15:00',
       '2016-01-01 13:30:00', '2016-01-01 13:45:00'], 
     'value': [1,2,2,2,4,5,5,7]}

df = pd.DataFrame(data=d)

df['date_time'] = pd.to_datetime(df['date_time'])

df_pivot = pd.pivot_table(df, index='value', values='date_time', aggfunc=[np.min,np.max])

df_pivot['duration'] = df_pivot.iloc[:, 1] - df_pivot.iloc[:, 0]

print(df_pivot[df_pivot['duration'] == max(df_pivot['duration'])])
groupby
+
nlargest
创建跟踪更改的分组系列

groupr = df.value.ne(df.value.shift()).cumsum()
创建一个映射字典,可以将
groupr
键转换为
df.value
列中的实际
value

mapper = dict(zip(groupr, df.value))
现在我们分组并使用
ptp
nlargest
。最后,我们使用
rename
mapper
索引
值(即
groupr
值)转换回
值(这有点混乱)

索引中的
2
是持续时间最长的
值。
0天00:30:00
是最长的持续时间

工具书类

是否可以在另一个条纹中再次出现
value
值?@Karlthorton相同的值可以在另一个条纹中再次出现,这将是一个不同的条纹。谢谢您的回答!这比我的问题更全面。.shift()和cumsum技术非常适合我的情况。事实上,上面的方法获取了
值的最长条纹,并给出了该条纹的持续时间,而不是任何条纹的最长持续时间。因此,我可能没有正确回答您的问题。更新我的答案的最长持续时间的任何连胜。谢谢。我喜欢你的答案给出了价值和持续时间。但是,当该值再次出现在另一个条纹中时,它不适用。请参阅我更新的示例。如果您能更新您的答案,我将不胜感激。谢谢:)看看这对你是否有意义。它现在返回正确的结果。但是“应用”似乎在我的实际数据帧上花费了很长时间,而实际数据帧要大得多。我想知道是否有更快的解决办法。谢谢。对不起,我没有把问题说清楚。请参阅我更新的示例。该值实际上可以出现在其他条纹中,但不应计算在内。非常感谢。
groupr = df.value.ne(df.value.shift()).cumsum()
mapper = dict(zip(groupr, df.value))
df.groupby(groupr).date_time.apply(np.ptp).nlargest(1).rename(mapper)

value
2   0 days 00:30:00
Name: date_time, dtype: timedelta64[ns]