Фильтрация данных по году, затем подсчет частоты двоичных состояний между интервалами значений - PullRequest
1 голос
/ 18 марта 2019

У меня есть фрейм данных, который выглядит следующим образом (показаны 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,5 мм / час, 2,5 - 5 мм / час и т. Д.), А затем 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», маскирование df по значению «Y» для создания отдельных фреймов данных для каждого года, затем применяя дополнительные маски к каждой из этих dfs, чтобы определить частоту между каждым интервалом ... Пожалуйста, кто-нибудь, помогите!

Надеюсь, это имеет смысл, и большое спасибо заранее :))

Ответы [ 2 ]

1 голос
/ 19 марта 2019

Один из подходов с использованием панд без пользовательских функций - это pd.cut столбец Imax в новый столбец типа данных 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
1 голос
/ 19 марта 2019

Вы можете использовать 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']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...