Pandas 按月份和年份分组

2025-03-04 08:25:00
admin
原创
75
摘要:问题描述:我有以下数据框:Date abc xyz 01-Jun-13 100 200 03-Jun-13 -20 50 15-Aug-13 40 -5 20-Jan-14 25 15 21-Feb-14 60 80 我需要按年份和月...

问题描述:

我有以下数据框:

Date        abc    xyz
01-Jun-13   100    200
03-Jun-13   -20    50
15-Aug-13   40     -5
20-Jan-14   25     15
21-Feb-14   60     80

我需要按年份和月份对数据进行分组。例如,按 2013 年 1 月、2013 年 2 月、2013 年 3 月等分组...

我将使用新分组的数据来创建一个显示每年/每月 abc 与 xyz 的图表。

我尝试过 groupby 和 sum 的各种组合,但似乎什么都不起作用。我该怎么做?


解决方案 1:

您可以使用重新采样或Grouper(在后台重新采样)。

首先确保 datetime 列确实是日期时间 (用pd.to_datetime)。如果是 DatetimeIndex 就更容易了:

In [11]: df1
Out[11]:
            abc  xyz
Date
2013-06-01  100  200
2013-06-03  -20   50
2013-08-15   40   -5
2014-01-20   25   15
2014-02-21   60   80

In [12]: g = df1.groupby(pd.Grouper(freq="M"))  # DataFrameGroupBy (grouped by Month)

In [13]: g.sum()
Out[13]:
            abc  xyz
Date
2013-06-30   80  250
2013-07-31  NaN  NaN
2013-08-31   40   -5
2013-09-30  NaN  NaN
2013-10-31  NaN  NaN
2013-11-30  NaN  NaN
2013-12-31  NaN  NaN
2014-01-31   25   15
2014-02-28   60   80

In [14]: df1.resample("M", how='sum')  # the same
Out[14]:
            abc  xyz
Date
2013-06-30   40  125
2013-07-31  NaN  NaN
2013-08-31   40   -5
2013-09-30  NaN  NaN
2013-10-31  NaN  NaN
2013-11-30  NaN  NaN
2013-12-31  NaN  NaN
2014-01-31   25   15
2014-02-28   60   80

注意:以前pd.Grouper(freq="M")写为pd.TimeGrouper("M")。后者自 0.21 版起已弃用。


我曾以为下面的方法可行,但实际上行不通(因为as_index不被尊重?我不确定。)。我出于兴趣才将其包括在内。

如果它是一列(它必须是 datetime64 列!正如我所说,用 命中它to_datetime),您可以使用 PeriodIndex:

In [21]: df
Out[21]:
        Date  abc  xyz
0 2013-06-01  100  200
1 2013-06-03  -20   50
2 2013-08-15   40   -5
3 2014-01-20   25   15
4 2014-02-21   60   80

In [22]: pd.DatetimeIndex(df.Date).to_period("M")  # old way
Out[22]:
<class 'pandas.tseries.period.PeriodIndex'>
[2013-06, ..., 2014-02]
Length: 5, Freq: M

In [23]: per = df.Date.dt.to_period("M")  # new way to get the same

In [24]: g = df.groupby(per)

In [25]: g.sum()  # dang not quite what we want (doesn't fill in the gaps)
Out[25]:
         abc  xyz
2013-06   80  250
2013-08   40   -5
2014-01   25   15
2014-02   60   80

为了获得期望的结果,我们必须重新索引......

解决方案 2:

保持简单:

GB = DF.groupby([(DF.index.year), (DF.index.month)]).sum()

给你,

print(GB)
        abc  xyz
2013 6   80  250
     8   40   -5
2014 1   25   15
     2   60   80

然后你可以像要求的那样绘制,

GB.plot('abc', 'xyz', kind='scatter')

解决方案 3:

有多种方法可以做到这一点。

  • 我创建了数据框来展示过滤数据的不同技术。

  df = pd.DataFrame({'Date': ['01-Jun-13', '03-Jun-13', '15-Aug-13', '20-Jan-14', '21-Feb-14'],
                     'abc': [100, -20, 40, 25, 60], 'xyz': [200, 50,-5, 15, 80] })
  • 我按照您解释的那样,分离了月份/年份/日期,并分离了月份/年份。

  def getMonth(s):
      return s.split("-")[1]

  def getDay(s):
      return s.split("-")[0]

  def getYear(s):
      return s.split("-")[2]

  def getYearMonth(s):
      return s.split("-")[1] + "-" + s.split("-")[2]
  • 我创建了新列:yearmonthdayyearMonth”。就你的情况而言,你需要其中之一。你可以使用两列'year','month'或一列进行分组yearMonth

  df['year'] = df['Date'].apply(lambda x: getYear(x))
  df['month'] = df['Date'].apply(lambda x: getMonth(x))
  df['day'] = df['Date'].apply(lambda x: getDay(x))
  df['YearMonth'] = df['Date'].apply(lambda x: getYearMonth(x))

输出:

        Date  abc  xyz year month day YearMonth
0  01-Jun-13  100  200   13   Jun  01    Jun-13
1  03-Jun-13  -20   50   13   Jun  03    Jun-13
2  15-Aug-13   40   -5   13   Aug  15    Aug-13
3  20-Jan-14   25   15   14   Jan  20    Jan-14
4  21-Feb-14   60   80   14   Feb  21    Feb-14
  • 您可以浏览 groupby(..) 项目中的不同组。

在这种情况下,我们按两列分组:

  for key, g in df.groupby(['year', 'month']):
      print key, g

输出:

('13', 'Jun')         Date  abc  xyz year month day YearMonth
0  01-Jun-13  100  200   13   Jun  01    Jun-13
1  03-Jun-13  -20   50   13   Jun  03    Jun-13
('13', 'Aug')         Date  abc  xyz year month day YearMonth
2  15-Aug-13   40   -5   13   Aug  15    Aug-13
('14', 'Jan')         Date  abc  xyz year month day YearMonth
3  20-Jan-14   25   15   14   Jan  20    Jan-14
('14', 'Feb')         Date  abc  xyz year month day YearMonth

在这种情况下,我们按一列分组:

  for key, g in df.groupby(['YearMonth']):
      print key, g

输出:

Jun-13         Date  abc  xyz year month day YearMonth
0  01-Jun-13  100  200   13   Jun  01    Jun-13
1  03-Jun-13  -20   50   13   Jun  03    Jun-13
Aug-13         Date  abc  xyz year month day YearMonth
2  15-Aug-13   40   -5   13   Aug  15    Aug-13
Jan-14         Date  abc  xyz year month day YearMonth
3  20-Jan-14   25   15   14   Jan  20    Jan-14
Feb-14         Date  abc  xyz year month day YearMonth
4  21-Feb-14   60   80   14   Feb  21    Feb-14
  • 如果你想访问特定项目,你可以使用get_group

  print df.groupby(['YearMonth']).get_group('Jun-13')

输出:

        Date  abc  xyz year month day YearMonth
0  01-Jun-13  100  200   13   Jun  01    Jun-13
1  03-Jun-13  -20   50   13   Jun  03    Jun-13
  • 类似于get_group。此 hack 有助于过滤值并获取分组值。

这也会产生相同的结果。

  print df[df['YearMonth']=='Jun-13']

输出:

        Date  abc  xyz year month day YearMonth
0  01-Jun-13  100  200   13   Jun  01    Jun-13
1  03-Jun-13  -20   50   13   Jun  03    Jun-13

您可以选择列表abcxyzJun-13

  print df[df['YearMonth']=='Jun-13'].abc.values
  print df[df['YearMonth']=='Jun-13'].xyz.values

输出:

[100 -20]  #abc values
[200  50]  #xyz values

您可以使用它来查找已分类为“年月”的日期并对其应用条件以获取相关数据。

  for x in set(df.YearMonth):
      print df[df['YearMonth']==x].abc.values
      print df[df['YearMonth']==x].xyz.values

我也建议检查一下这个答案。

解决方案 4:

您还可以通过创建包含年份和月份的字符串列来实现此目的,如下所示:

df['date'] = df.index
df['year-month'] = df['date'].apply(lambda x: str(x.year) + ' ' + str(x.month))
grouped = df.groupby('year-month')

但是,当你循环遍历组时,这不会保留顺序,例如

for name, group in grouped:
    print(name)

将会给予:

2007 11
2007 12
2008 1
2008 10
2008 11
2008 12
2008 2
2008 3
2008 4
2008 5
2008 6
2008 7
2008 8
2008 9
2009 1
2009 10

因此,如果您想保留订单,您必须按照上面@Q-man 的建议进行操作:

grouped = df.groupby([df.index.year, df.index.month])

这将保留上述循环中的顺序:

(2007, 11)
(2007, 12)
(2008, 1)
(2008, 2)
(2008, 3)
(2008, 4)
(2008, 5)
(2008, 6)
(2008, 7)
(2008, 8)
(2008, 9)
(2008, 10)

解决方案 5:

一些答案使用Date索引而不是列(这样做没有错)。

但是,如果您将日期存储为列(而不是索引),请记住访问该列的dt属性。即:

# First make sure `Date` is a datetime column
df['Date'] = pd.to_datetime(
  arg=df['Date'],
  format='%d-%b-%y' # Assuming dd-Mon-yy format
)

# Group by year and month
df.groupby(
  [
    df['Date'].dt.year,
    df['Date'].dt.month 
  ]
).sum()

解决方案 6:

一种简单且更通用的方法是创建一个列,其中包含您想要的数据箱。对于这个问题,箱将是年份和月份。请注意,由于您正在绘制结果,因此您不需要包含没有数据的月份。

该索引将转换为日期时间索引,并将用于创建容器。该groupby方法在处理容器时删除列,容器将成为索引中的行。可选地,索引可以在最后再次转换为日期时间索引,以允许正确排序。

import pandas as pd

idx = ['01-Jun-13', '03-Jun-13', '15-Aug-13', '20-Jan-14', '21-Feb-14']
data = {'abc': [100, -20, 40, 25, 60],
        'xyz': [200, 50, -5, 15, 80]}

df = pd.DataFrame(index=idx, data=data)
df.index = pd.to_datetime(df.index, format='%d-%b-%y')
df['bin'] = df.index.strftime('%Y-%m-01')
result = df.groupby('bin').sum()
result.index = pd.to_datetime(result.index)

df现在result是:

In [1]: df
Out[1]: 
            abc  xyz         bin
2013-06-01  100  200  2013-06-01
2013-06-03  -20   50  2013-06-01
2013-08-15   40   -5  2013-08-01
2014-01-20   25   15  2014-01-01
2014-02-21   60   80  2014-02-01

In [2]: result
Out[2]: 
            abc  xyz
bin                 
2013-06-01   80  250
2013-08-01   40   -5
2014-01-01   25   15
2014-02-01   60   80
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2766  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1694  
  在全球化的浪潮下,企业的业务范围不断拓展,跨文化协作变得愈发普遍。不同文化背景的团队成员在合作过程中,由于语言、价值观、工作习惯等方面的差异,往往会面临诸多沟通挑战。而产品生命周期管理(PLM)系统作为企业管理产品全生命周期的重要工具,如何有效支持跨文化协作成为了关键问题。通过合理运用沟通策略,PLM系统能够在跨文化团...
plm是什么软件   22  
  PLM(产品生命周期管理)系统在企业的产品研发、生产与管理过程中扮演着至关重要的角色,其中文档版本控制是确保产品数据准确性、完整性和可追溯性的关键环节。有效的文档版本控制能够避免因版本混乱导致的错误、重复工作以及沟通不畅等问题,提升企业整体的运营效率和产品质量。接下来,我们将深入探讨 PLM 系统实现文档版本控制的 6...
plm是什么意思   25  
  PLM(产品生命周期管理)项目管理旨在通过有效整合流程、数据和人员,优化产品从概念到退役的整个生命周期。在这个过程中,敏捷测试成为确保产品质量、加速交付的关键环节。敏捷测试强调快速反馈、持续改进以及与开发的紧密协作,对传统的测试流程提出了新的挑战与机遇。通过对测试流程的优化,能够更好地适应PLM项目的动态变化,提升产品...
plm管理系统   25  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用