2014-10-30 107 views
19

我有以下数据框:熊猫GROUPBY月份和年份

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 vs xyz的图。

我试过groupby和sum的各种组合,但似乎无法得到任何工作。

感谢您的协助。

回答

39

您可以使用重采样或TimeGrouper(重新采样在引擎盖下使用)。

首先使日期时间列实际上是日期时间(用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.TimeGrouper("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 

我原以为下面会的工作,但它不会(因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 

为了让我们不得不重新索引所需的结果。 ..

+0

感谢您的帮助。我无法让TimeGrouper工作,但重新采样(“M”)完成了这个诀窍。然而,只是fyi,它需要参数how ='sum'。我现在唯一的问题是剧情正在使用滴答标签的完整日期时间。我需要它显示每个酒吧的月份和年份。再次感谢。 – darkpool 2014-10-30 13:58:57

7

有不同的方法来做到这一点。

  • 我创建了数据框来展示不同的技术来过滤数据。
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] 
  • 我创造了新的栏目:yearmonthday和 'yearMonth'。在你的情况下,你需要两者之一。您可以使用两列'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

打印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类似。这种破解将有助于过滤值并获得分组值。

这也会给出相同的结果。

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 

您可以选择abcxyz值列表中Jun-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 

您可以使用此工具查看您已分类为“年 - 月”的日期,并在其上应用cretiria以获取相关数据。

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

我推荐也检查这个answer以及。

+0

对于任何日期在这个格式为'2016-08-11',改变'def getYearMonth(s): return s.split(“ - ”)[1] +“ - ”+ s.split(“ - ”)[2]'def getYearMonth(s): return s.split(“ - ”)[0] +“ - ”+ s.split(“ - ”)[1]'输出'2016-08' – 2017-07-15 14:19:22

23

为什么不保持简单?!

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

你也可以做到这一点通过创建年份和月份字符串列如下:

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-人以上的建议:

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)