2013-09-01 51 views
48

Giả sử tôi có nhật ký hoạt động của người dùng và tôi muốn tạo báo cáo tổng thời lượng và số lượng người dùng duy nhất mỗi ngày.Tổng số gấu trúc tổng hợp riêng biệt

import numpy as np 
import pandas as pd 
df = pd.DataFrame({'date': ['2013-04-01','2013-04-01','2013-04-01','2013-04-02', '2013-04-02'], 
    'user_id': ['0001', '0001', '0002', '0002', '0002'], 
    'duration': [30, 15, 20, 15, 30]}) 

thời gian Tập hợp khá đơn giản:

group = df.groupby('date') 
agg = group.aggregate({'duration': np.sum}) 
agg 
      duration 
date 
2013-04-01  65 
2013-04-02  45 

sum Những gì tôi muốn làm là thời gian và đếm distincts cùng một lúc, nhưng tôi dường như không thể tìm thấy một tương đương cho count_distinct:

agg = group.aggregate({ 'duration': np.sum, 'user_id': count_distinct}) 

Công trình này, nhưng chắc chắn có cách tốt hơn, phải không?

group = df.groupby('date') 
agg = group.aggregate({'duration': np.sum}) 
agg['uv'] = df.groupby('date').user_id.nunique() 
agg 
      duration uv 
date 
2013-04-01  65 2 
2013-04-02  45 1 

Tôi nghĩ mình chỉ cần cung cấp hàm trả về số mục riêng biệt của đối tượng Series cho hàm tổng hợp, nhưng tôi không có nhiều hiển thị với các thư viện khác nhau vứt bỏ. Ngoài ra, có vẻ như đối tượng groupby đã biết thông tin này, vì vậy tôi sẽ không được nhân đôi nỗ lực?

Trả lời

86

Làm thế nào về một trong hai:

>>> df 
     date duration user_id 
0 2013-04-01  30 0001 
1 2013-04-01  15 0001 
2 2013-04-01  20 0002 
3 2013-04-02  15 0002 
4 2013-04-02  30 0002 
>>> df.groupby("date").agg({"duration": np.sum, "user_id": pd.Series.nunique}) 
      duration user_id 
date       
2013-04-01  65  2 
2013-04-02  45  1 
>>> df.groupby("date").agg({"duration": np.sum, "user_id": lambda x: x.nunique()}) 
      duration user_id 
date       
2013-04-01  65  2 
2013-04-02  45  1 
+1

Vậy là xong. pd.Series.nunique là những gì tôi không thể tìm thấy, tốt, không thể hoạt động chính xác. Khá rõ ràng trong nhận thức. Cảm ơn! – dave

+1

Câu trả lời này đã lỗi thời. Bây giờ bạn có thể sử dụng 'nunique' trực tiếp. Xem giải pháp của @Blodwyn Pig bên dưới –

13

'nunique' bây giờ là một lựa chọn cho .agg(), vì vậy:

df.groupby('date').agg({'duration': 'sum', 'user_id': 'nunique'}) 
+0

Có thể tăng cường và nhận các giá trị duy nhất không? một cái gì đó như 'thời gian: np.unique' – guy

3

Chỉ cần thêm vào các câu trả lời đã được đưa ra, giải pháp @Blodwyn Pig là hiệu quả nhất.

giải pháp này có vẻ nhanh hơn nhiều, thử nghiệm ở đây trên ~ hàng 21M dataframe, sau đó nhóm lại để ~ 2M

%time _=g.agg({"id": lambda x: x.nunique()}) 
CPU times: user 3min 3s, sys: 2.94 s, total: 3min 6s 
Wall time: 3min 20s 

%time _=g.agg({"id": pd.Series.nunique}) 
CPU times: user 3min 2s, sys: 2.44 s, total: 3min 4s 
Wall time: 3min 18s 

%time _=g.agg({"id": 'nunique'}) 
CPU times: user 14 s, sys: 4.76 s, total: 18.8 s 
Wall time: 24.4 s 
+1

Đẹp bắt! Tôi đoán nó là b/c trong một "lambda"/"chức năng khác" trường hợp nó được áp dụng tuần tự, trong khi "được biết đến" chức năng được áp dụng cho toàn bộ cột trong một thời trang vectorized. – Ufos

Các vấn đề liên quan