【问题标题】:How to group pandas DataFrame entries by date in a non-unique column如何在非唯一列中按日期对 Pandas DataFrame 条目进行分组
【发布时间】:2012-07-08 16:04:10
【问题描述】:

Pandas DataFrame 包含名为 "date" 的列,其中包含非唯一的 datetime 值。 我可以使用以下方法对该框架中的行进行分组:

data.groupby(data['date'])

但是,这会按datetime 值拆分数据。我想按存储在“日期”列中的年份对这些数据进行分组。 This page 展示了在时间戳用作索引的情况下如何按年份分组,而我的情况并非如此。

如何实现这种分组?

【问题讨论】:

  • 对于那些在 2017 年及以上来到这里的人,有几种新方法可以按特定时间量进行分组。 See this answer below

标签: python pandas


【解决方案1】:

我正在使用熊猫 0.16.2。这在我的大型数据集上具有更好的性能:

data.groupby(data.date.dt.year)

使用dt 选项并使用weekofyear、dayofweek 等变得容易得多。

【讨论】:

  • 同意,这似乎是访问系列日期属性的熊猫方式。
【解决方案2】:

ecatmur 的解决方案可以正常工作。不过,这将在大型数据集上表现更好:

data.groupby(data['date'].map(lambda x: x.year))

【讨论】:

  • 为什么映射而不是应用?
  • Afaik,map 在应用任意函数时通常比仅使用 apply 具有一些良好的效率品质。
【解决方案3】:

使用示例数据集可能更容易解释。

创建示例数据

假设我们有一列时间戳 date 和另一列我们要对其执行聚合的列 a。

df = pd.DataFrame({'date':pd.DatetimeIndex(['2012-1-1', '2012-6-1', '2015-1-1', '2015-2-1', '2015-3-1']),
                   'a':[9,5,1,2,3]}, columns=['date', 'a'])

df

        date  a
0 2012-01-01  9
1 2012-06-01  5
2 2015-01-01  1
3 2015-02-01  2
4 2015-03-01  3

有几种按年份分组的方法

  • 将 dt 访问器与 year 属性结合使用
  • 将date放入索引并使用匿名函数访问年份
  • 使用resample方法
  • 转换为 pandas 周期

.dt 具有 year 属性的访问器

当您有一列(而不是索引)熊猫时间戳时,您可以使用 dt 访问器访问更多额外的属性和方法。例如:

df['date'].dt.year

0    2012
1    2012
2    2015
3    2015
4    2015
Name: date, dtype: int64

我们可以使用它来形成我们的组并计算特定列上的一些聚合:

df.groupby(df['date'].dt.year)['a'].agg(['sum', 'mean', 'max'])

      sum  mean  max
date                
2012   14     7    9
2015    6     2    3

将日期放入索引并使用匿名函数访问年份

如果将日期列设置为索引,它将成为 DateTimeIndex,其属性和方法与 dt 访问器提供的普通列相同

df1 = df.set_index('date')
df1.index.year

Int64Index([2012, 2012, 2015, 2015, 2015], dtype='int64', name='date')

有趣的是,当使用 groupby 方法时,您可以向它传递一个函数。此函数将隐式传递 DataFrame 的索引。所以,我们可以从上面得到相同的结果:

df1.groupby(lambda x: x.year)['a'].agg(['sum', 'mean', 'max'])

      sum  mean  max
2012   14     7    9
2015    6     2    3

使用resample 方法

如果您的日期列不在索引中,则必须使用on 参数指定该列。您还需要将offset alias 指定为字符串。

df.resample('AS', on='date')['a'].agg(['sum', 'mean', 'max'])

             sum  mean  max
date                       
2012-01-01  14.0   7.0  9.0
2013-01-01   NaN   NaN  NaN
2014-01-01   NaN   NaN  NaN
2015-01-01   6.0   2.0  3.0

转换为 pandas 周期

您还可以将日期列转换为 pandas Period 对象。我们必须将偏移别名作为字符串传入,以确定 Period 的长度。

df['date'].dt.to_period('A')

0   2012
1   2012
2   2015
3   2015
4   2015
Name: date, dtype: object

然后我们可以将其用作一个组

df.groupby(df['date'].dt.to_period('Y'))['a'].agg(['sum', 'mean', 'max'])


      sum  mean  max
2012   14     7    9
2015    6     2    3

【讨论】:

  • 在你使用to_period('A')的最后一个方法中,那个('A')是干什么用的?
  • @Shiv_90 'A' 是一个时间序列偏移别名:pandas.pydata.org/pandas-docs/stable/…
  • 如果还需要保存单独的“日期”列,您会推荐哪种方法?例如,如果我运行简单的.dt.year 方法并将其保存在一个新的数据框中,日期将保存为索引,如果说我需要绘制数据,因为“日期”列并不存在,但只有.agg()中提供的三个
【解决方案4】:

这应该可行:

data.groupby(lambda x: data['date'][x].year)

【讨论】:

    【解决方案5】:

    这也行

    data.groupby(data['date'].dt.year)

    【讨论】:

    • 应该可以工作,但执行时会输出对象在内存中的位置,但没有实际输出。 <pandas.core.groupby.DataFrameGroupBy object at 0x10d7f6438> 是我执行时得到的。
    【解决方案6】:

    用途:

    data.groupby(['col1', data.date.dt.year]).agg({'col2': 'agg_func'}).reset_index()
    

    如果您想从日期时间列和另一个不同类型的列 (col1) 按年份分组

    【讨论】:

      猜你喜欢
      • 2013-12-06
      • 1970-01-01
      • 1970-01-01
      • 2022-07-07
      • 2014-05-15
      • 2013-01-16
      • 2017-03-18
      • 2015-09-01
      • 2021-12-17
      相关资源
      最近更新 更多