具有项目计数的有效分组

2024-06-02 21:08:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我的数据集如下所示:

Name | Country
---------------
Alex | USA
Tony | DEU
Alex | GBR
Alex | USA

我试着把这样的东西弄出来,基本上是分组和计数:

Name | Country
---------------
Alex | {USA:2,GBR:1}
Tony | {DEU:1}

工作正常,但在大型数据集上运行缓慢

下面是我的代码,它确实适用于较小的df,但在较大的df上却需要很长时间(我的代码大约有1400万行)。我也使用多处理模块来加速,但没有多大帮助:

def countNames(x):
    return dict(Counter(x))

def aggregate(df_full,nameList):
    df_list = []
    for q in nameList:
        df = df_full[df_full['Name']==q]
        df_list.append(df.groupby('Name')['Country'].apply(lambda x: str(countNames(x))).to_frame().reset_index()) 
    return pd.concat(df_list)

df = pd.DataFrame({'Name':['Alex','Tony','Alex','Alex'], 
                'Country':['USA','GBR','USA','DEU']})[['Name','Country']]

aggregate(df,df.Name.unique())

有没有什么可以加速内部逻辑(除了运行多处理)?你知道吗


Tags: 数据代码namedfreturndefcountryfull
3条回答

这基本上是一个交叉表。您所说的“类似于此”意味着您不太确定输出应该是什么。你知道吗

选项1
分组依据和value_counts

df.groupby('Name').Country.value_counts()

Name  Country
Alex  USA        2
      GBR        1
Tony  DEU        1
Name: Country, dtype: int64

要获取指定的输出:

pd.Series({
    name: pd.value_counts(d).to_dict()
    for name, d in df.groupby('Name').Country
}).rename_axis('Name').reset_index(name='Country')

   Name               Country
0  Alex  {'USA': 2, 'GBR': 1}
1  Tony            {'DEU': 1}

选项2
不过,我更喜欢这些陈述。我们可以在the answer to question # 9 in this answer中看到很多方法

pd.crosstab(df.Name, df.Country)

Country  DEU  GBR  USA
Name                  
Alex       0    1    2
Tony       1    0    0

对于O(n)复杂性解决方案,使用^{}。你知道吗

from collections import Counter, defaultdict
import pandas as pd

df = pd.DataFrame({'Name':['Alex','Tony','Alex','Alex'], 
                   'Country':['USA','GBR','USA','DEU']})[['Name','Country']]

c = Counter(map(tuple, df.values))

# Counter({('Alex', 'DEU'): 1, ('Alex', 'USA'): 2, ('Tony', 'GBR'): 1})

字典结果

然后,您可以通过^{}获得名称->;国家/地区词典映射。我不会把字典放在pandas数据框中,它不是为这个目的而设计的。你知道吗

tree = lambda: defaultdict(tree)
d = tree()

for k, v in c.items():
    d[k[0]][k[1]] = v

for k, v in d.items():
    print(k, v)

# Alex defaultdict(<function <lambda>>, {'USA': 2, 'DEU': 1})
# Tony defaultdict(<function <lambda>>, {'GBR': 1})

数据帧结果

出于显示目的,可以直接从defaultdict构建数据帧:

res_df = pd.DataFrame.from_dict(d, orient='index').fillna(0)

#       USA  DEU  GBR
# Alex  2.0  1.0  0.0
# Tony  0.0  0.0  1.0

你在找这个吗?你知道吗

import pandas as pd

df = pd.DataFrame({'Name':['Alex','Tony','Alex','Alex'], 
                'Country':['USA','GBR','USA','DEU']})[['Name','Country']]

df = (df.groupby('Name')['Country']
         .apply(lambda x: str(x.value_counts().to_dict()))
         .reset_index(name='Country'))

退货:

   Name               Country
0  Alex  {'USA': 2, 'DEU': 1}
1  Tony            {'GBR': 1}

相关问题 更多 >