簡體   English   中英

根據Python Pandas中的其他列對列進行分組

[英]Group columns based on other columns in Python Pandas

假設我有以下pd.DataFrame

Name | Color
------------------------------
John | Blue
Greg | Red
John | Yellow
Greg | Red
Greg | Blue

我想得到一個表格,列出每個名字的不同顏色 - 多少和它們的價值。 意思是這樣的:

Name | Distinct | Values
--------------------------------------
John |   2      | Blue, Yellow
Greg |   2      | Red, Blue

有什么想法怎么做?

使用groupby + agg ,傳遞自定義聚合函數list

f = [
        ('Distinct', 'nunique'), 
        ('Values', lambda x: ', '.join(x.unique()))
]

df.groupby('Name').Color.agg(f).reset_index()

   Name  Distinct        Values
0  Greg         2     Red, Blue
1  John         2  Blue, Yellow

計時

一,設置 -

df = pd.DataFrame(
      np.random.randint(0, 1000, (10000, 2)).astype(str), columns=['Name', 'Color']
)

接下來,時間安排。 似乎pd.Series.unique非常慢(慢4倍)。 為了性能,我將使用np.unique代替:

# in this answer

%%timeit
f = [
        ('Distinct', 'nunique'), 
        ('Values', lambda x: ', '.join(np.unique(x.values).tolist()))
]

df.groupby('Name').Color.agg(f).reset_index()

122 ms ± 1.51 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

使用lambda x: ', '.join(x.unique())導致4倍的減速。 使用set對這些數據更快一些,但它確實取決於。

# @jpp

%%timeit
v = df.groupby('Name')['Color'].apply(set).reset_index()
v['Distinct'] = v['Color'].map(len)
v['Color'] = v['Color'].map(', '.join)

219 ms ± 1.83 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

# @jezrael

%%timeit
(df.groupby('Name')['Color'].agg(['nunique', lambda x: ', '.join(set(x))])
        .rename(columns={'nunique':'Distinct', '<lambda>':'Values'})
        .reset_index())

118 ms ± 4.29 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

性能隨數據變化很大 ,您可能希望在決定使用什么之前為所有解決方案計算自己的數據。

使用groupby with agg ,last rename columns和reset_index

df = (df.groupby('Name')['Color'].agg(['nunique', lambda x: ', '.join(set(x))])
        .rename(columns={'nunique':'Distinct', '<lambda>':'Values'})
        .reset_index())
print (df)
   Name  Distinct        Values
0  Greg         2     Blue, Red
1  John         2  Blue, Yellow

避免低效lambda一種方法:

df = df.groupby('Name')['Color'].apply(set).reset_index()

df['Distinct'] = df['Color'].map(len)
df['Color'] = df['Color'].map(', '.join)

#    Name         Color  Distinct
# 0  Greg     Red, Blue         2
# 1  John  Yellow, Blue         2

順便說一句,我注意到了方法鏈和/或單線計算的趨勢。 如果性能不是問題,我建議使用您發現更有用/可讀的內容。 就個人而言,我更喜歡將計算分為3個部分。

績效基准

import pandas as pd
import numpy as np
from random import choice
from string import ascii_uppercase

df = pd.DataFrame({'Name': np.random.randint(0, 100, 10000),
                   'Color': [''.join(choice(ascii_uppercase) for _ in range(2)) for k in range(10000)]})

def jpp(df):
    df = df.groupby('Name')['Color'].apply(set).reset_index()

    df['Distinct'] = df['Color'].map(len)
    df['Color'] = df['Color'].map(', '.join)
    return df

def jez(df):
    return df.groupby('Name')['Color'].agg(['nunique', lambda x: ', '.join(set(x))])\
            .rename(columns={'nunique':'Distinct', '<lambda>':'Values'})\
            .reset_index()

def cs(df):
    f = [
            ('Distinct', 'nunique'), 
            ('Values', lambda x: ', '.join(x.unique()))
    ]

    return df.groupby('Name').Color.agg(f).reset_index()

%timeit jpp(df)  # 100 loops, best of 3: 15.7 ms per loop
%timeit jez(df)  # 10 loops, best of 3: 22.9 ms per loop
%timeit cs(df)   # 10 loops, best of 3: 27.1 ms per loop

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM