2013-02-21 34 views
23

Tôi có một khung dữ liệu và tôi muốn nhóm nó theo một cột cụ thể (hoặc, nói cách khác, bằng các giá trị từ một cột cụ thể). Tôi có thể thực hiện theo cách sau: grouped = df.groupby(['ColumnName']).Làm cách nào để áp dụng các hàm "đầu tiên" và "cuối cùng" cho các cột trong khi sử dụng nhóm theo gấu trúc?

Tôi tưởng tượng kết quả của thao tác này dưới dạng bảng trong đó một số ô có thể chứa tập giá trị thay vì giá trị đơn. Để có được một bảng thông thường (tức là một bảng trong đó mỗi ô chỉ chứa một giá trị duy nhất), tôi cần chỉ ra hàm nào tôi muốn sử dụng để chuyển đổi tập các giá trị trong các ô thành các giá trị đơn.

Ví dụ: tôi có thể thay thế tập giá trị theo tổng của chúng hoặc bằng giá trị tối thiểu hoặc tối đa của chúng. Tôi có thể thực hiện theo cách sau: grouped.sum() hoặc grouped.min() và cứ tiếp tục như vậy.

Bây giờ tôi muốn sử dụng các chức năng khác nhau cho các cột khác nhau. Tôi đã tìm ra rằng tôi có thể thực hiện theo cách sau: grouped.agg({'ColumnName1':sum, 'ColumnName2':min}).

Tuy nhiên, vì một số lý do tôi không thể sử dụng first. Để biết thêm chi tiết, grouped.first() hoạt động, nhưng grouped.agg({'ColumnName1':first, 'ColumnName2':first}) không hoạt động. Kết quả là tôi nhận được một NameError: NameError: name 'first' is not defined. Vì vậy, câu hỏi của tôi là: Tại sao nó xảy ra và làm thế nào để giải quyết vấn đề này.

THÊM

Here tôi thấy ví dụ sau:

grouped['D'].agg({'result1' : np.sum, 'result2' : np.mean}) 

Có thể là tôi cũng cần phải sử dụng np? Nhưng trong trường hợp của tôi python không nhận ra "np". Tôi có nên nhập nó không?

+0

Bạn không cần 'np', nó sẽ hoạt động với' sum' cũ (chỉ kém hiệu quả hơn). numpy được nhập khẩu với gấu trúc (nếu bạn 'nhập gấu trúc như pd' đó là' pd.np') nhưng hầu hết mọi người cũng sẽ nhập nó một cách riêng biệt để thuận tiện. –

Trả lời

23

Tôi nghĩ rằng vấn đề là có hai phương pháp khác nhau first có chung tên nhưng hành động khác nhau, một là dành cho groupby objectsanother for a Series/DataFrame (để làm với thời gian).

Để tái tạo các hành vi của các phương pháp groupby first hơn một DataFrame sử dụng agg bạn có thể sử dụng iloc[0] (mà được dòng đầu tiên trong mỗi nhóm (DataFrame/Series) bởi index):

grouped.agg(lambda x: x.iloc[0]) 

Ví dụ:

In [1]: df = pd.DataFrame([[1, 2], [3, 4]]) 

In [2]: g = df.groupby(0) 

In [3]: g.first() 
Out[3]: 
    1 
0 
1 2 
3 4 

In [4]: g.agg(lambda x: x.iloc[0]) 
Out[4]: 
    1 
0 
1 2 
3 4 

Tương tự bạn có thể sao chép last sử dụng iloc[-1].

Lưu ý: Điều này sẽ làm việc cột-khôn ngoan, et al:

g.agg({1: lambda x: x.iloc[0]}) 

Trong phiên bản cũ của gấu trúc bạn có thể sẽ sử dụng phương pháp irow (ví dụ x.irow(0), xem chỉnh sửa trước


.

Một vài lưu ý được cập nhật:

Điều này được thực hiện tốt hơn bằng cách sử dụng nth phương pháp groupby, đó là nhanh hơn nhiều> = 0,13:

g.nth(0) # first 
g.nth(-1) # last 

Bạn cần phải chăm sóc một chút, như hành vi mặc định cho firstlast bỏ qua hàng NaN ... và IIRC cho DataFrame groupbys nó đã bị hỏng trước 0.13 ... có tùy chọn dropna cho nth.

Bạn có thể sử dụng các dây chứ không phải là built-in (mặc dù điểm gấu trúc IIRC đó là sum dựng sẵn và áp dụng np.sum):

grouped['D'].agg({'result1' : "sum", 'result2' : "mean"}) 
+0

Chỉ trong trường hợp nó hữu ích cho bất kỳ ai, theo [tài liệu] (http://pandas.pydata.org/pandas-docs/dev/indexing.html), 'irow' bây giờ không còn được dùng nữa (' x.iloc [0] 'thay vào đó) – cd98

+0

@ cd98 Cảm ơn bạn đã chỉ ra điều đó, tôi đã cập nhật điều này với cú pháp mới hơn :) –

+0

Tôi đang nhầm lẫn với [ tài liệu] (http://pandas.pydata.org/pandas-docs/stable/groupby.html#aggregation); nó nói: 'Các hàm tổng hợp là các hàm làm giảm kích thước của các đối tượng được trả về, ví dụ: trung bình, tổng, kích thước, số đếm, std, var, sem, description, first, last, n, min, max.' họ nói về? – Tjorriemorrie

0

Tôi không chắc đây có phải là vấn đề hay không, nhưng summin là trình xây dựng Python dùng một số lần lặp lại làm đầu vào, trong khi first là một phương thức của đối tượng chuỗi gấu trúc, vì vậy có thể nó không nằm trong không gian tên của bạn. Hơn nữa nó lấy một cái gì đó khác như một đầu vào (doc cho biết một số giá trị bù đắp).

Tôi đoán một cách để có được xung quanh nó là để tạo ra first chức năng của riêng bạn, và xác định nó như vậy mà phải mất một đối tượng dòng như một đầu vào, ví dụ:

def first(Series, offset): 
    return Series.first(offset) 

hoặc một cái gì đó như thế ..

+0

Thật tiếc là 'pd.Series.first' không hoạt động – Tjorriemorrie

6

Thay vì sử dụng first hoặc last, sử dụng cơ quan đại diện chuỗi của họ trong agg phương pháp. Ví dụ về trường hợp của OP:

grouped = df.groupby(['ColumnName']) 
grouped['D'].agg({'result1' : np.sum, 'result2' : np.mean}) 

#you can do the string representation for first and last 
grouped['D'].agg({'result1' : 'first', 'result2' : 'last'}) 
Các vấn đề liên quan