2014-10-30 53 views
19

Tôi có dataframe sau:Pandas groupby tháng, năm

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 

tôi cần phải nhóm các dữ liệu theo năm và tháng. ví dụ: Nhóm vào tháng 1 năm 2013, tháng 2 năm 2013, tháng 3 năm 2013, v.v ... Tôi sẽ sử dụng dữ liệu được nhóm mới để tạo một biểu đồ hiển thị abc so với xyz mỗi năm/tháng.

Tôi đã thử các kết hợp nhóm và tổng hợp khác nhau nhưng dường như dường như không có gì để làm việc.

Cảm ơn bạn đã hỗ trợ.

Trả lời

39

Bạn có thể sử dụng một trong hai mẫu lại hoặc TimeGrouper (mà việc lấy mẫu lại sử dụng dưới mui xe).

Đầu tiên, làm cho cột ngày giờ thực sự là datetimes (nhấn nó với pd.to_datetime). Sẽ dễ dàng hơn nếu nó muốn một 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 

tôi đã nghĩ sau đây sẽ làm việc, nhưng nó không (do as_index không được tôn trọng tôi không chắc chắn?.), Tôi m bao gồm điều này vì lợi ích.

Nếu đó là một cột (! Nó có phải là một cột datetime64 như tôi nói, nhấn nó với to_datetime), bạn có thể sử dụng 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 

Để có được kết quả mong muốn chúng ta phải reindex. ..

+0

Cảm ơn sự giúp đỡ. Tôi không thể có được TimeGrouper để làm việc, nhưng resample ("M") đã làm các trick. Tuy nhiên, chỉ cần fyi, nó yêu cầu đối số how = 'sum'. Vấn đề duy nhất của tôi bây giờ là cốt truyện đang sử dụng datetime đầy đủ cho các nhãn tick. Tôi cần nó để chỉ hiển thị tháng và năm cho mỗi thanh. Cảm ơn một lần nữa. – darkpool

7

Có nhiều cách khác nhau để thực hiện điều đó.

  • Tôi đã tạo khung dữ liệu để hiển thị các kỹ thuật khác nhau để lọc dữ liệu của bạn.
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]})

  • Tôi đã tách riêng các tháng/năm/ngày và được phân cách trong năm theo tháng như bạn đã giải thích.
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] 
  • Tôi tạo ra các cột mới: year, month, day và 'yearMonth'. Trong trường hợp của bạn, bạn cần một trong cả hai. Bạn có thể sử dụng nhóm hai cột 'year','month' hoặc sử dụng một cột 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)) 

Output:

 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 
  • Bạn có thể đi qua các nhóm khác nhau trong groupby (..) mục .

Trong trường hợp này, chúng tôi được nhóm bởi hai cột:

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

Output:

('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 

Trong trường hợp này, chúng tôi được nhóm bởi một cột:

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

Output:.

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 
  • Trong trường hợp bạn truy cập muốn các đề mục cụ thể, bạn có thể sử dụng get_group

in df.groupby ([ 'nămTháng']) get_group ('Jun-13')

Đầu ra:

 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 
  • Tương tự như get_group. Hack này sẽ giúp lọc các giá trị và nhận các giá trị được nhóm.

Điều này cũng sẽ cho kết quả tương tự.

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

Output:

 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 

Bạn có thể chọn danh sách abc hoặc xyz giá trị trong Jun-13

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

Output:

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

Bạn có thể sử dụng điều này để đi qua những ngày bạn đã phân loại là "năm tháng" và áp dụng cretiria vào nó để nhận dữ liệu liên quan.

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

Tôi cũng khuyên bạn cũng nên kiểm tra điều này answer.

+0

Đối với bất kỳ ai có ngày trong định dạng này '2016-08-11', thay đổi' def getYearMonth (s): trả về s.split ("-") [1] + "-" + s.split ("-") [2] 'để xóa getYearMonth (s): trả về s.split ("-") [0] + "-" + s.split ("-") [1] 'để lấy kết quả« 2016-08' –

23

Tại sao không giữ nó đơn giản ?!

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

đem lại cho bạn,

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

và sau đó bạn có thể vẽ giống như hỏi sử dụng,

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

Bạn cũng có thể làm điều đó bằng cách tạo ra một cột chuỗi với năm và tháng như sau :

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

Tuy nhiên điều này không bảo toàn thứ tự khi bạn lặp lại các nhóm, ví dụ:

for name, group in grouped: 
    print(name) 

Sẽ cung cấp:

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 

Vì vậy, sau đó, nếu bạn muốn giữ gìn trật tự, bạn phải làm theo đề nghị của @ Q-người đàn ông ở trên:

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

này sẽ giữ gìn đơn đặt hàng trong vòng lặp ở trên:

(2007, 11) 
(2007, 12) 
(2008, 1) 
(2008, 2) 
(2008, 3) 
(2008, 4) 
(2008, 5) 
(2008, 6) 
(2008, 7) 
(2008, 8) 
(2008, 9) 
(2008, 10) 
Các vấn đề liên quan