Добавление за пропущенные месяцы в фрейм данных с нулевыми значениями - PullRequest
0 голосов
/ 11 февраля 2019

У меня есть DataFrame, с которым я пытаюсь найти частоту определенных событий.Так, например, он указан следующим образом:

Month Year Event UniqueID
1     2018 A     01
1     2018 A     02
2     2018 B     03
....

и т. Д.У меня есть все, сгруппированные по частоте событий в год.Я сделал это, используя следующий код:

Это подсчитывает все события, чтобы я мог усреднить их

df.groupby(['Year','Month','Event'])['Event'].size().rename('Count of Events').reset_index()

Что дает нам что-то вроде

Year Month Event Count of Events
2018 01    A     2
2018 02    B     1
...

А потом я получаю среднее значение, как часто это происходит в месяц за весь год, используя

df.groupby(['Event'])['Count of Events'].mean()

, что дает мне среднее значение.Однако я заметил одну вещь: у меня могут быть пробелы.Например, событие «А» может происходить в январе и феврале, но не в марте, поэтому это не даст мне истинное «среднее» за год.Каков был бы лучший способ «заткнуть» эти дыры?Например, в приведенном выше списке примеров,

Month Year Event Count of Events
1     2018 A     02
1     2018 B     00
1     2018 C     00
2     2018 A     00
2     2018 B     00
2     2018 B     01
...

будет оптимальным окончательным результатом, прежде чем я его усредню.Спасибо!

Ответы [ 3 ]

0 голосов
/ 11 февраля 2019

Вы были близки к решению.После группировки снимите стек данных с «широкой» формы (таким образом, вы будете иметь каждую комбинацию месяца и года), заполните пропущенные значения нулями и сложите их обратно:

df.groupby(["Month", "Year", "Event"]).size().unstack().fillna(0).stack()
#Month  Year  Event
#1      2018  A        2.0
#             B        0.0
#2      2018  A        0.0
#             B        1.0
0 голосов
/ 11 февраля 2019

Решение, предложенное DYZ , производит данные только за «настоящие» месяцы.

Но рассмотрим исходные данные следующим образом:

df = pd.DataFrame(data=[
    [ 1, 2018, 'A', '01' ], [ 1, 2018, 'A', '02' ], [ 2, 2018, 'B', '03' ],
    [ 4, 2018, 'A', '04' ], [ 4, 2018, 'A', '05' ], [ 7, 2018, 'A', '06' ],
    [ 7, 2018, 'B', '07' ], [ 7, 2018, 'B', '08' ] ],
    columns=['Month', 'Year', 'Event', 'UniqueID'])

, где нет данныхза март, май и июнь, поэтому результат, напечатанный в соответствии с DYZ , будет иметь «пробелы».

Обратите внимание, что такая деталь, касающаяся «пробелов», является исходными данными:

  • Для некоторых типов событий вы можете иметь «отсутствующие» данные также для первый и / или последний месяц.
  • Но, тем не менее, по крайней мере, на мой взглядсреднее значение true должно быть рассчитано как сумма событий определенного типа, деленная на количество месяцев всей активности , а не на промежуток месяцев текущая активность.

Например, в моей выборке данных, если первое событие было в январе, а последнее в июле независимо от типа события , то вся операциязаняло 7 месяцев.

Так что одним из шагов должно быть вычисление MonthNo - числа мес.тыс. целых действий.

Другое предложение состоит в том, чтобы «переключиться» с отдельных Год / Месяц столбцы на Дата (DateTime) и установите его в качестве индекса.Этот столбец (на самом деле индекс) понадобится в какой-то момент (см. Ниже).

Итак, мое предложение по написанию сценария таково:

import pandas as pd
import math

# Source data
df = pd.DataFrame(data=[ [ 1, 2018, 'A', '01' ], [ 1, 2018, 'A', '02' ],
    [ 2, 2018, 'B', '03' ], [ 4, 2018, 'A', '04' ], [ 4, 2018, 'A', '05' ],
    [ 7, 2018, 'A', '06' ], [ 7, 2018, 'B', '07' ], [ 7, 2018, 'B', '08' ] ],
    columns=['Month', 'Year', 'Event', 'UniqueID'])
# Count of Events
df2 = df.groupby(['Year','Month','Event'])['Event'].size()\
    .rename('Count of Events').reset_index()
# Replace Year / Month with Dat
df2['Dat'] = pd.to_datetime(df2.Year * 10000 + df2.Month * 100 + 1,
    format='%Y%m%d')
df2.drop(columns=['Year', 'Month'], inplace=True)
df2.set_index('Dat', inplace=True)
# How many months took the activity
MonthNo = math.ceil((df2.index.max() - df2.index.min())/np.timedelta64(1, 'M')) + 1

Затем, если вы хотите иметь строкис нулевым количеством событий для «промежутков» месяцев, вызовите resample для каждого типа события (здесь нужен индекс DateTime):

df3 = df2.groupby(['Event']).resample('MS').sum()

Результат:

                  Count of Events
Event Dat                        
A     2018-01-01                2
      2018-02-01                0
      2018-03-01                0
      2018-04-01                2
      2018-05-01                0
      2018-06-01                0
      2018-07-01                1
B     2018-02-01                1
      2018-03-01                0
      2018-04-01                0
      2018-05-01                0
      2018-06-01                0
      2018-07-01                2

И чтобы вычислить среднее число событий каждого типа в месяц для всей деятельности , позвоните:

df3.groupby(level=0).sum() / MonthNo

и получите:

       Count of Events
Event                 
A             0.714286
B             0.428571

Обратите внимание, что resample было необходимо только для того, чтобы получить месяцы без пробелов, а не вычислять средние числа.

0 голосов
/ 11 февраля 2019

Я думаю, что вам нужно это fillna: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html

Это действительно простой способ заполнить нулевые значения и указать, чем их заполнить.

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