将缺失的月份添加到具有空值的数据框中

时间:2019-02-11 16:56:51

标签: python pandas dataframe

我有一个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()

哪个给我平均值。但是我注意到的一件事是我可能有差距。例如,事件“ A”可能发生在1月和2月,而不是3月,所以这不会给我一年的真实“平均值”。填补这些孔的最佳方法是什么?例如,在上面的示例列表中,

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 :(得分:3)

您已接近解决方案。分组后,将数据框堆叠为“宽”形式(这样,您将获得一个月和一年的每种组合),将缺失的值填充为0,然后将其堆叠回去:

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

答案 1 :(得分:1)

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'])

由于没有3月,5月和6月的数据,因此结果根据 DYZ 将具有“空白”。

请注意,有关“空白”的详细信息是源数据:

  • 对于某些事件类型,您还可以第一和/或具有“缺席”数据 最后个月。
  • 但是,至少在我看来,应该计算 true 平均值 特定类型事件的总和除以 整个活动,而不是当前活动的前几个月。

例如在我的数据样本中,如果第一个事件发生在1月,而最后一个事件发生在7月, 无论事件类型如何,整个活动耗时 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

请注意,仅需要重新采样即可获得数月的空白, 不要计算平均值。

答案 2 :(得分:0)

我认为您需要的是fillna:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html

这是填充空值并指定要填充空值的简单方法。