Tổng số gấu trúc khác biệt


94

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 về tổng thời lượng và số lượng người dùng duy nhất mỗi ngày.

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 lượng tổng 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

Những gì tôi muốn làm là tổng hợp thời lượng và đếm bản năng cùng một lúc, nhưng tôi dường như không thể tìm thấy một điểm tương đương cho count_distinct:

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

Điều này hoạt động, nhưng chắc chắn có một cách tốt hơn, 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ĩ rằng tôi chỉ cần cung cấp một hàm trả về số lượng các mục riêng biệt của một đối tượng Dòng cho hàm tổng hợp, nhưng tôi không có nhiều khả năng tiếp xúc với các thư viện khác nhau theo ý của mình. Ngoài ra, có vẻ như đối tượng theo nhóm đã biết thông tin này, vì vậy tôi sẽ không cố gắng sao chép?

Câu trả lời:


155

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

>>> 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
Đó là nó. 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 muộn màng. Cảm ơn!
dave

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

Cảm ơn @TedPetrou, tôi là Coder trước đây gọi là Blodwyn Pig;)
Ricky McMaster

Này, bạn có biết làm thế nào để có được số lượng không trùng lặp không?
Ambleu

61

'nunique' là một tùy chọn cho .agg () vì pandas 0.20.0, vì vậy:

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

Có thể tổng hợp và nhận các giá trị duy nhất không? một cái gì đó giống nhưduration: np.unique
anh chàng

@guy Trydf.groupby('date').agg({'user_id': lambda s: s.unique().reset_index(drop=True)})
BallpointBen.

Làm thế nào để chúng tôi có được đầu ra?

17

Chỉ cần thêm vào các câu trả lời đã cho, giải pháp sử dụng chuỗi "nunique"có vẻ nhanh hơn nhiều, được thử nghiệm ở đây trên khung dữ liệu ~ 21M hàng, sau đó được nhóm lại thành ~ 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
Bắt đẹp! Tôi đoán đó là b / c trong trường hợp "lambda" / "hàm khác", nó được áp dụng tuần tự, trong khi các hàm "đã biết" được áp dụng cho toàn bộ cột theo kiểu vectơ hóa.
Ufos

giải pháp nào là từ @Blodwyn Pig?
Chogg

@Chogg, người nhanh nhất!
m-dz

@Chogg - xin lỗi tôi đã thay đổi tên người dùng của mình. Nó là tôi.
Ricky McMaster
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.