当前位置: 首页 > 面试题库 >

如何总结不同的groupby组合?

景宏朗
2023-03-14
问题内容

我正在按县列出前三名的作物表。一些县以相同的顺序拥有相同的农作物品种。其他县具有相同的作物品种,但顺序不同。

df1 = pd.DataFrame( { 
    "County" : ["Harney", "Baker", "Wheeler", "Hood River", "Wasco" , "Morrow","Union","Lake"] , 
    "Crop1" : ["grain", "melons", "melons", "apples", "pears", "raddish","pears","pears"],
    "Crop2" : ["melons","grain","grain","melons","carrots","pears","carrots","carrots"],
    "Crop3": ["apples","apples","apples","grain","raddish","carrots","raddish","raddish"],
    "Total_pop": [2000,1500,3000,1500,2000,2500,2700,2000]} )

我可以对Crop1,Crop2和Crop3进行分组,并获得total_pop的总和:

df1_grouped=df1.groupby(['Crop1',"Crop2","Crop3"])['Total_pop'].sum().reset_index()

这给了我特定作物组合的总数:

df1_grouped
apples  melons  grain   1500
grain   melons  apples  2000
melons  grain   apples  4500
pears   carrots raddish 6700
raddish pears   carrots 2500

不过,我想获得的是不同作物组合的总人口-无论列出的作物是crop1,crop2还是crop3。理想的结果是这样的:

apples  melons   grain    8000
pears   carrots  raddish  9200

感谢您的指导。


问题答案:

方法1:

合并crop

>>> df1['combined_temp'] = df1.apply(lambda x : list([x['Crop1'],
...                           x['Crop2'],
...                           x['Crop3']]),axis=1)
>>> df1.head()
       County   Crop1    Crop2    Crop3  Total_pop              combined_temp
0      Harney   grain   melons   apples       2000    [grain, melons, apples]
1       Baker  melons    grain   apples       1500    [melons, grain, apples]
2     Wheeler  melons    grain   apples       3000    [melons, grain, apples]
3  Hood River  apples   melons    grain       1500    [apples, melons, grain]
4       Wasco   pears  carrots  raddish       2000  [pears, carrots, raddish]

使它成为一个排序的元组

>>> df1['sorted'] = df1.apply(lambda x : tuple(sorted(x['combined_temp'])),axis=1)
>>> df1.head()
       County   Crop1    Crop2            ...             Total_pop              combined_temp                     sorted
0      Harney   grain   melons            ...                  2000    [grain, melons, apples]    (apples, grain, melons)
1       Baker  melons    grain            ...                  1500    [melons, grain, apples]    (apples, grain, melons)
2     Wheeler  melons    grain            ...                  3000    [melons, grain, apples]    (apples, grain, melons)
3  Hood River  apples   melons            ...                  1500    [apples, melons, grain]    (apples, grain, melons)
4       Wasco   pears  carrots            ...                  2000  [pears, carrots, raddish]  (carrots, pears, raddish)

然后按操作进行常规分组

>>> df1_grouped = df1.groupby(['sorted'])['Total_pop'].sum().reset_index()
>>> df1_grouped
                      sorted  Total_pop
0    (apples, grain, melons)       8000
1  (carrots, pears, raddish)       9200

方法2: 基于ws-apprentice的答案的简短

    df = df1.copy()

    grouping_cols = ['Crop1', 'Crop2', 'Crop3']

    df[grouping_cols] = pd.DataFrame(df.loc[:, grouping_cols] \
                                .apply(html" target="_blank">set, axis=1) \
                                .apply(sorted)            
                                .values \
                                .tolist(), columns=grouping_cols)

    >>> df.head()
           County    Crop1  Crop2    Crop3  Total_pop
    0      Harney   apples  grain   melons       2000
    1       Baker   apples  grain   melons       1500
    2     Wheeler   apples  grain   melons       3000
    3  Hood River   apples  grain   melons       1500
    4       Wasco  carrots  pears  raddish       2000

现在按组分组

    >>> df.groupby(grouping_cols).Total_pop.sum()
    Crop1    Crop2  Crop3  
    apples   grain  melons     8000
    carrots  pears  raddish    9200
    Name: Total_pop, dtype: int64

但我个人更喜欢使用numpy这个答案

由于您的数据似乎可以保证每个国家/地区拥有3种独特的农作物(“我正在按县级列出前三名的农作物一览表。”),因此可以对值进行排序并重新分配。

import numpy as np

cols = ['Crop1', 'Crop2', 'Crop3']
df1[cols] = np.sort(df1[cols].values, axis=1)

       County    Crop1  Crop2    Crop3  Total_pop
0      Harney   apples  grain   melons       2000
1       Baker   apples  grain   melons       1500
2     Wheeler   apples  grain   melons       3000
3  Hood River   apples  grain   melons       1500
4       Wasco  carrots  pears  raddish       2000
5      Morrow  carrots  pears  raddish       2500
6       Union  carrots  pears  raddish       2700
7        Lake  carrots  pears  raddish       2000

然后总结一下:

df1.groupby(cols).sum()

#                       Total_pop
#Crop1   Crop2 Crop3             
#apples  grain melons        8000
#carrots pears raddish       9200

好处是您避免使用Series.apply或.apply(axis=1)。对于large DataFrames,性能差异非常明显:

df1 = pd.concat([df1]*10000, ignore_index=True)

cols = ['Crop1', 'Crop2', 'Crop3']
%timeit df1[cols] = np.sort(df1[cols].values, axis=1)
#36.1 ms ± 399 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

to_sum = ['Crop1', 'Crop2', 'Crop3']
%timeit df1[to_sum] = pd.DataFrame(df1.loc[:, to_sum].apply(set, axis=1).apply(list).values.tolist(), columns=to_sum)
#1.41 s ± 51.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)


 类似资料:
  • 问题内容: 我想解析一个json文件,但它经过这样的事情: 但是大约有三千个这样的对象。我一直在使用Gson解析我的json对象,但是我怎么解析这种文件呢?以及如何检索名称“ CDG”或“ ORY”? 问题答案: 您可以尝试如下操作: 使用gson,您可以按以下方式检索键名: 并使用java- json 可以执行以下操作: 从网址获取json:

  • 本文向大家介绍AQS 组件总结 相关面试题,主要包含被问及AQS 组件总结 时的应答技巧和注意事项,需要的朋友参考一下 Semaphore(信号量)-允许多个线程同时访问: synchronized 和 ReentrantLock 都是一次只允许一个线程访问 某个资源,Semaphore(信号量)可以指定多个线程同时访问某个资源。 CountDownLatch (倒计时器): CountDownL

  • 主要内容:一维数组,二维数组,数组操作,数组排序,常见问题解答,应用实例数组(Array)是有序数据的集合,数组中的每个元素具有相同的数据类型,可以用一个统一的数组名和不同的下标来唯一确定数组中的元素。根据数组的维度,可以将其分为一维数组、二维数组和多维数组等。 一维数组 数组中每个元素都只带有一个下标,是数组中最简单的一种数组。 1. 声明 声明一维数组语法有两种格式(推荐使用第一种)。 type[] arrayName;    // 数据类型[] 数组名; 或者

  • 根据给定的函数对数组元素进行分组。 使用 Array.map() 将数组的值映射到函数或属性名称。使用 Array.reduce() 来创建一个对象,其中的 key 是从映射结果中产生。 const groupBy = (arr, fn) => arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i

  • 我正在尝试选择一些不在我的中的属性。这可能吗? 如何从中获取CatId和持久属性? 如果我将它们添加到组中,就像,那么我的结果就会混乱。 我可以使用获得其他属性,如,但这些属性不是计算值。 数据示例: 希望将结果按如下方式分组:

  • 我想通过使用join_date进行分组并得到平均数量(通过将数量相加然后除以有数量的记录数来制定;不考虑没有数量的记录)。 输入 以下是预期输出的示例: 输出 非常感谢。