Python 如何在pandas中映射一个函数,将列中的每条记录与上一条记录和下一条记录进行比较

Python 如何在pandas中映射一个函数,将列中的每条记录与上一条记录和下一条记录进行比较,python,pandas,Python,Pandas,我有一个水位的时间序列,我需要计算几个任意洪水阶段的月度和年度统计数据。具体来说,我需要确定每月超过洪水水位的持续时间,以及这些偏移发生的次数。此外,由于数据记录器的噪音,我需要排除持续时间小于1小时的洪水以及事件间隔小于1小时的洪水 模型数据: start = datetime.datetime(2014,9,5,12,00) daterange = pd.date_range(start, periods = 10000, freq = '30min', name = "Datetime")

我有一个水位的时间序列,我需要计算几个任意洪水阶段的月度和年度统计数据。具体来说,我需要确定每月超过洪水水位的持续时间,以及这些偏移发生的次数。此外,由于数据记录器的噪音,我需要排除持续时间小于1小时的洪水以及事件间隔小于1小时的洪水

模型数据:

start = datetime.datetime(2014,9,5,12,00)
daterange = pd.date_range(start, periods = 10000, freq = '30min', name = "Datetime")
data = np.random.random_sample((len(daterange), 3)) * 10
columns = ["Pond_A", "Pond_B", "Pond_C"]
df = pd.DataFrame(data = data, index = daterange, columns = columns)
flood_stages = [('Stage_1', 4.0), ('Stage_2', 6.0)]
我期望的输出是:

                          Pond_A_Stage_1_duration Pond_A_Stage_1_events  \
2014-09-30 12:00:00                    35.5                  2   
2014-10-31 12:00:00                    40.5                  31   
2014-11-30 12:00:00                    100                   16   
2014-12-31 12:00:00                    36                    12   
各水库各洪水期的持续时间和事件

我试着按月分组,遍历池塘,然后遍历每一行,如下所示:

grouper = pd.TimeGrouper(freq = "1MS")
month_groups = df.groupby(grouper)
for name, group in month_groups:
    flood_stage_a = group.sum()[1]
    flood_stage_b = group.sum()[2]
    inundation_a = False
    inundation_30_a = False
    inundation_hour_a = False
    change_inundation_a = 0
    for level in group.values:
        if level[1]:
            inundation_a = True
        else:
            inundation_a = False
        if inundation_hour_a == False and inundation_a == True and inundation_30_a == True:
            change_inundation_a += 1
        inundation_hour_a = inundation_30_a
        inundation_30_a = inundation_a
但这是一个穴居人的解决方案,而启发式算法变得混乱,因为如果洪水在一个月内开始并持续到下一个月,我不想计算新的事件。这也不包括从开始到结束不到一小时的事件。有没有更好的方法将记录与上一个记录和下一个记录进行比较


我的另一个想法是用序列移位的t+1、t+2、t-1、t-2创建新列,这样我可以对每一行计算一次,但这似乎仍然效率低下。有没有更聪明的方法通过映射函数来实现这一点?

让我给出一个快速、部分的答案,因为目前还没有人回答,如果这还不足以满足您的要求,也许其他人以后可以做得更好

你可以很容易地计算洪水水位以上的时间。我除以48,所以单位是天

df[ df > 4 ].groupby(pd.TimeGrouper( freq = "1MS" )).count() / 48

               Pond_A     Pond_B     Pond_C
Datetime                                   
2014-09-01  15.375000  15.437500  14.895833
2014-10-01  18.895833  18.187500  18.645833
2014-11-01  17.937500  17.979167  18.666667
2014-12-01  18.104167  18.354167  18.958333
2015-01-01  18.791667  18.645833  18.708333
2015-02-01  16.583333  17.208333  16.895833
2015-03-01  18.458333  18.458333  18.458333
2015-04-01   0.458333   0.520833   0.500000
计算不同的事件有点困难,但像这样的事情会让你得到大部分的方法。(请注意,这会产生大量不切实际的洪水事件,但这只是因为样本数据是如何设置的,而不是典型池塘的反映,尽管我不是池塘洪水方面的专家!)


如果您共享您正在工作的数据表以及所需的输出,这将有所帮助!谢谢你,我知道熊猫有一个聪明的方法来做到这一点,但我真的是在风中扭曲试图解决它。
for c in df.columns:
    df[c+'_events'] = ((df[c] > 4) & (df[c].shift() <= 4))

df.iloc[:,-3:].groupby(pd.TimeGrouper( freq = "1MS" )).sum()

            Pond_A_events  Pond_B_events  Pond_C_events
Datetime                                               
2014-09-01            306            291            298
2014-10-01            381            343            373
2014-11-01            350            346            357
2014-12-01            359            352            361
2015-01-01            355            335            352
2015-02-01            292            337            316
2015-03-01            344            360            386
2015-04-01              9             10              9
df[c+'_events'] = ((df[c]           > 4) & (df[c].shift(1) <= 4) &
                   (df[c].shift(-1) > 4) & (df[c].shift(2) <= 4))
            Pond_A_events  Pond_B_events  Pond_C_events
Datetime                                               
2014-09-01             70             71             72
2014-10-01             91             85             81
2014-11-01             87             75             91
2014-12-01             88             87             77
2015-01-01             91             95             94
2015-02-01             79             90             83
2015-03-01             83             78             85
2015-04-01              0              2              2