按年份过滤数据帧,然后计算值间隔之间的二进制状态频率

时间:2019-03-18 20:22:24

标签: pandas dataframe

我有一个看起来像这样的数据框(显示了底部的6个条目):

            Imax        SzT 
date                            
2017-09-14  10.139999   0.0 
2017-09-15  0.000000    0.0 
2017-09-16  0.000000    0.0 
2017-09-17  0.000000    0.0 
2017-09-18  0.200000    0.0
2017-09-19  12.710000   1.0

此数据框可以追溯到1998年,并显示日期,该日期的最大降雨强度(Imax)以及是否发生了洪水(SzT,为0或1)。

我希望1)按年份细分2)计算不同间隔(例如0-2.5mm / hr,2.5-5mm / hr等)之间的降雨强度频率,然后3)产生在这些时间间隔内(或不发生)洪水事件的数量的计数。我对结果的想法看起来像这样:

             2015
interval     no flood    flood     
0 - 2.5      27          1
2.5 - 5      15          1
5 - 10       7           4
10 - 15      3           3
15 - 20      1           3

             2016
interval     no flood    flood     
0 - 2.5      24          0
2.5 - 5      17          0
5 - 10       6           2
10 - 15      6           1
15 - 20      3           2

             2017
interval     no flood    flood     
0 - 2.5      32          0
2.5 - 5      19          0
5 - 10       9           0
10 - 15      4           0
15 - 20      2           1

我的最终目标是计算给定降雨强度间隔下给定年份洪水的频繁发生概率,并显示其随时间的变化。

到目前为止,我一直想将这种数据框拆分的方法非常繁琐,包括为“ Y”年添加一列,用“ Y”值掩盖df来创建每年的单个数据框,然后对每个df进一步应用遮罩,以确定每个间隔之间的频率...请帮助任何人!

我希望这是有道理的,并预先感谢一大堆:)

2 个答案:

答案 0 :(得分:1)

您可以使用groupby,这是一种方法:

首先创建一些随机数据以供播放:

import pandas as pd
import random

df = pd.DataFrame()
df['date'] = pd.date_range(start='01/01/2000', end='01/01/2010')
df['Imax'] = [random.randint(0,200)/10 for x in range(df.shape[0])]
df['SzT'] = [random.randint(0,1) for x in range(df.shape[0])]

然后创建了一个将值转换为间隔的函数:

intervals = list(zip([x/2 for x in list(range(0,40,5))], [x/2 for x in list(range(5,45,5))]))

def to_interval(x):
    for i in intervals:
        if i[0]<=x<i[1]:
            return i

然后添加了时间间隔和年份列:

df['interval'] = [to_interval(x) for x in df.Imax.values]
df['year'] = [x.year for x in df.date]

然后分组以求和(洪水天数)并计数:

grouped = df.groupby(['year', 'interval'])
result = grouped.agg({'SzT':['count', 'sum']})

然后从计数中减去总和,得到无洪水日的数量:

 result['SzT', 'count_minus_sum'] = result['SzT', 'count'] - result['SzT', 'sum']

答案 1 :(得分:1)

使用没有自定义帮助函数的熊猫的一种方法是将pd.cutImax放入数据类型为category的新列中,然后groupby使用其他条件:

# Simplified example data; read with df = pd.read_clipboard()

            Imax        SzT 
date                            
2017-09-14  10.139999   1.0 
2017-09-15  0.000000    0.0 
2017-09-16  0.000000    0.0 
2017-09-17  0.000000    0.0 
2017-09-18  0.200000    0.0
2017-09-19  12.710000   1.0
2016-03-01  3           0
2016-05-10  6           0
2016-09-20  12          1
2016-09-20  14          1
2015-03-01  0           0
2015-03-02  6           0
2015-04-15  19          1
2015-05-20  13          0

# Ensure index is a DatetimeIndex
df.index = pd.to_datetime(df.index)

# Cut float column into category column
df['interval'] = pd.cut(df['Imax'], bins=bins, right=False)

# Group by year, interval, and flood flag
(df.groupby([df.index.year, 'interval', 'SzT'])
   .size()
   .unstack()
   .fillna(0)
   .astype(int)
   .rename({0: 'no flood', 1: 'flood'}, axis=1))

SzT                no flood  flood
date interval                     
2015 [0.0, 2.5)           1      0
     [5.0, 10.0)          1      0
     [10.0, 15.0)         1      0
     [15.0, 20.0)         0      1
2016 [2.5, 5.0)           1      0
     [5.0, 10.0)          1      0
     [10.0, 15.0)         0      2
2017 [0.0, 2.5)           4      0
     [10.0, 15.0)         0      2