จำนวนรวมของหมีแพนด้าแตกต่างกัน


97

สมมติว่าฉันมีบันทึกกิจกรรมของผู้ใช้และฉันต้องการสร้างรายงานระยะเวลารวมและจำนวนผู้ใช้ที่ไม่ซ้ำกันต่อวัน

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]})

ระยะเวลารวมค่อนข้างตรงไปตรงมา:

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

สิ่งที่ฉันต้องการจะทำคือรวมระยะเวลาและนับความแตกต่างในเวลาเดียวกัน แต่ฉันไม่สามารถหาสิ่งที่เทียบเท่าสำหรับ count_distinct ได้:

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

วิธีนี้ได้ผล แต่ก็มีวิธีที่ดีกว่านี้ใช่ไหม

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

ฉันคิดว่าฉันแค่ต้องจัดเตรียมฟังก์ชันที่ส่งคืนการนับรายการที่แตกต่างกันของออบเจ็กต์ซีรีส์ไปยังฟังก์ชันการรวม แต่ฉันไม่ได้เปิดรับไลบรารีต่างๆมากนัก นอกจากนี้ดูเหมือนว่าวัตถุ groupby จะรู้ข้อมูลนี้อยู่แล้วดังนั้นฉันจะไม่พยายามทำซ้ำหรือไม่?

คำตอบ:


159

แล้วอย่างใดอย่างหนึ่ง:

>>> 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
แค่นั้นแหละ. pd.Series.nunique คือสิ่งที่ฉันหาไม่พบทำงานไม่ถูกต้อง ค่อนข้างชัดเจนในการมองย้อนกลับ ขอบคุณ!
dave

7
คำตอบนี้ล้าสมัย ตอนนี้คุณสามารถใช้งานnuniqueได้โดยตรง ดูวิธีแก้ปัญหาของ @Blodwyn Pig ด้านล่าง
Ted Petrou

ขอบคุณ @TedPetrou ฉันเป็น Coder เดิมรู้จักกันในชื่อ Blodwyn Pig;)
Ricky McMaster

เฮ้คุณรู้วิธีรับจำนวนที่ไม่ซ้ำกันไหม
Ambleu

65

'nunique' เป็นตัวเลือกสำหรับ. agg () เนื่องจากแพนด้า 0.20.0 ดังนั้น:

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

เป็นไปได้หรือไม่ที่จะ agg และรับค่าเฉพาะ คล้ายduration: np.unique
ผู้ชาย

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

เราจะได้ผลลัพธ์อย่างไร?

19

เพียงเพิ่มคำตอบที่ให้ไปแล้วการแก้ปัญหาโดยใช้สตริง"nunique"ดูเหมือนจะเร็วกว่ามากทดสอบที่นี่บนดาต้าเฟรม ~ 21M แถวจากนั้นจัดกลุ่มเป็น ~ 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

2
รับได้สวย! ฉันเดาว่ามันเป็น b / c ในกรณี "lambda" / "ฟังก์ชันอื่น ๆ " ซึ่งจะถูกนำไปใช้ตามลำดับในขณะที่ฟังก์ชัน "ทราบ" จะถูกนำไปใช้กับทั้งคอลัมน์ในรูปแบบเวกเตอร์
Ufos

วิธีแก้ปัญหาจาก @Blodwyn Pig?
Chogg

@ โชคเร็วที่สุด!
m-dz

@Chogg - ขออภัยฉันเปลี่ยนชื่อผู้ใช้ มันคือฉัน.
Ricky McMaster
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.