Сгруппируйте по столбцу и обновите дату и получите скользящую сумму другого столбца - PullRequest
2 голосов
/ 09 июля 2019

У меня есть следующие данные:

(Pdb) df1 = pd.DataFrame({'id': ['SE0000195570','SE0000195570','SE0000195570','SE0000195570','SE0000191827','SE0000191827','SE0000191827','SE0000191827', 'SE0000191827'],'val': ['1','2','3','4','5','6','7','8', '9'],'date': pd.to_datetime(['2014-10-23','2014-07-16','2014-04-29','2014-01-31','2018-10-19','2018-07-11','2018-04-20','2018-02-16','2018-12-29'])})

(Pdb) df1
             id val       date
0  SE0000195570   1 2014-10-23
1  SE0000195570   2 2014-07-16
2  SE0000195570   3 2014-04-29
3  SE0000195570   4 2014-01-31
4  SE0000191827   5 2018-10-19
5  SE0000191827   6 2018-07-11
6  SE0000191827   7 2018-04-20
7  SE0000191827   8 2018-02-16
8  SE0000191827   9 2018-12-29

ОБНОВЛЕНИЕ: В соответствии с предложениями @ user3483203 я продвинулся немного дальше, но не совсем там.Я изменил приведенные выше примеры данных новой строкой, чтобы лучше проиллюстрировать.

(Pdb) df2.assign(calc=(df2.dropna()['val'].groupby(level=0).rolling(4).sum().shift(-3).reset_index(0, drop=True)))
                                   id  val       date  calc
id           date                                          
SE0000191827 2018-02-28  SE0000191827    8 2018-02-16  26.0
             2018-03-31           NaN  NaN        NaT   NaN
             2018-04-30  SE0000191827    7 2018-04-20  27.0
             2018-05-31           NaN  NaN        NaT   NaN
             2018-06-30           NaN  NaN        NaT   NaN
             2018-07-31  SE0000191827    6 2018-07-11   NaN
             2018-08-31           NaN  NaN        NaT   NaN
             2018-09-30           NaN  NaN        NaT   NaN
             2018-10-31  SE0000191827    5 2018-10-19   NaN
             2018-11-30           NaN  NaN        NaT   NaN
             2018-12-31  SE0000191827    9 2018-12-29   NaN
SE0000195570 2014-01-31  SE0000195570    4 2014-01-31  10.0
             2014-02-28           NaN  NaN        NaT   NaN
             2014-03-31           NaN  NaN        NaT   NaN
             2014-04-30  SE0000195570    3 2014-04-29   NaN
             2014-05-31           NaN  NaN        NaT   NaN
             2014-06-30           NaN  NaN        NaT   NaN
             2014-07-31  SE0000195570    2 2014-07-16   NaN
             2014-08-31           NaN  NaN        NaT   NaN
             2014-09-30           NaN  NaN        NaT   NaN
             2014-10-31  SE0000195570    1 2014-10-23   NaN

Для моих требований строка (SE0000191827, 2018-03-31) должна иметь значение calc, поскольку оно имеет четыре последовательныхстроки со значением.В настоящее время строка удаляется с помощью вызова dropna, и я не могу понять, как решить эту проблему.


Что мне нужно

Вычисления: Даты в моих исходных данных - квартальные даты.Однако мне нужно преобразовать эти данные в месячные строки в диапазоне от первой до последней даты каждого id и для каждого месяца вычислить сумму четырех ближайших последовательных строк входных данных в этом id.Это полный рот.Это привело меня к resample.Смотрите ожидаемый результат ниже.Мне нужно, чтобы данные были сгруппированы по идентификатору и месячным датам.

Производительность: Данные, которые я сейчас тестирую, предназначены только для сравнительного анализа, но мне нужно решение, чтобы быть быстрым,Я ожидаю, что это будет увеличено до 100 000 уникальных id с, что может привести к примерно 10 миллионам строк.(100 000 идентификаторов, даты варьируются до 10 лет, 10 лет * 12 месяцев = 120 месяцев для каждого идентификатора, 100 000 * 120 = 12 миллионов строк).

Что я пробовал

(Pdb) res = df.groupby('id').resample('M',on='date')
(Pdb) res.first()
                                   id  val       date
id           date                                    
SE0000191827 2018-02-28  SE0000191827    8 2018-02-16
             2018-03-31           NaN  NaN        NaT
             2018-04-30  SE0000191827    7 2018-04-20
             2018-05-31           NaN  NaN        NaT
             2018-06-30           NaN  NaN        NaT
             2018-07-31  SE0000191827    6 2018-07-11
             2018-08-31           NaN  NaN        NaT
             2018-09-30           NaN  NaN        NaT
             2018-10-31  SE0000191827    5 2018-10-19
SE0000195570 2014-01-31  SE0000195570    4 2014-01-31
             2014-02-28           NaN  NaN        NaT
             2014-03-31           NaN  NaN        NaT
             2014-04-30  SE0000195570    3 2014-04-29
             2014-05-31           NaN  NaN        NaT
             2014-06-30           NaN  NaN        NaT
             2014-07-31  SE0000195570    2 2014-07-16
             2014-08-31           NaN  NaN        NaT
             2014-09-30           NaN  NaN        NaT
             2014-10-31  SE0000195570    1 2014-10-23

ЭтоДанные выглядят очень хорошо для моего случая, так как они сгруппированы по id и имеют date, выстроенные по месяцам.Здесь кажется, что я мог бы использовать что-то вроде df['val'].rolling(4) и убедиться, что оно пропускает значения NaN и поместить этот результат в новый столбец.

Ожидаемый результат (новый столбец calc):

                                   id  val       date  calc
id           date                                    
SE0000191827 2018-02-28  SE0000191827    8 2018-02-16    26
             2018-03-31           NaN  NaN        NaT
             2018-04-30  SE0000191827    7 2018-04-20   NaN
             2018-05-31           NaN  NaN        NaT
             2018-06-30           NaN  NaN        NaT
             2018-07-31  SE0000191827    6 2018-07-11   NaN
             2018-08-31           NaN  NaN        NaT
             2018-09-30           NaN  NaN        NaT
             2018-10-31  SE0000191827    5 2018-10-19   NaN
SE0000195570 2014-01-31  SE0000195570    4 2014-01-31    10
             2014-02-28           NaN  NaN        NaT
             2014-03-31           NaN  NaN        NaT
             2014-04-30  SE0000195570    3 2014-04-29   NaN
             2014-05-31           NaN  NaN        NaT
             2014-06-30           NaN  NaN        NaT
             2014-07-31  SE0000195570    2 2014-07-16   NaN
             2014-08-31           NaN  NaN        NaT
             2014-09-30           NaN  NaN        NaT
             2014-10-31  SE0000195570    1 2014-10-23   NaN
             2014-11-30           NaN  NaN        NaT
             2014-12-31  SE0000195570    1 2014-10-23   NaN

Здесь результат в calc равен 26 для первой даты, поскольку он добавляет три предыдущих (8 + 7 + 6 + 5).Остальное для id - NaN, поскольку четыре значения недоступны.

Проблемы

Хотя может показаться, что данные сгруппированы по id и date, кажется,как будто он на самом деле сгруппирован по date.Я не уверен, как это работает.Мне нужно, чтобы данные были сгруппированы по идентификатору и дате.

(Pdb) res['val'].get_group(datetime.date(2018,2,28))
7    6.730000e+08
Name: val, dtype: object

Результат resample выше возвращает DatetimeIndexResamplerGroupby, который не имеет rolling ...

(Pdb) res['val'].rolling(4)
*** AttributeError: 'DatetimeIndexResamplerGroupby' object has no attribute 'rolling'

Что делать?Я предполагаю, что мой подход неверен, но после изучения документации я не уверен, с чего начать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...