使用 groupby 的 Pandas 占总数的百分比

Posted

技术标签:

【中文标题】使用 groupby 的 Pandas 占总数的百分比【英文标题】:Pandas percentage of total with groupby 【发布时间】:2014-06-16 03:00:59 【问题描述】:

这显然很简单,但作为一个 numpy 新手,我被卡住了。

我有一个 CSV 文件,其中包含 3 列,即州、办公室 ID 和该办公室的销售额。

我想计算给定州每个办公室的销售额百分比(每个州所有百分比的总和为 100%)。

df = pd.DataFrame('state': ['CA', 'WA', 'CO', 'AZ'] * 3,
                   'office_id': range(1, 7) * 2,
                   'sales': [np.random.randint(100000, 999999)
                             for _ in range(12)])

df.groupby(['state', 'office_id']).agg('sales': 'sum')

这会返回:

                  sales
state office_id        
AZ    2          839507
      4          373917
      6          347225
CA    1          798585
      3          890850
      5          454423
CO    1          819975
      3          202969
      5          614011
WA    2          163942
      4          369858
      6          959285

我似乎不知道如何“达到”groupbystate 级别,以合计整个statesales 来计算分数。

【问题讨论】:

df['sales'] / df.groupby('state')['sales'].transform('sum') 似乎是最明确的答案。 【参考方案1】:

Paul H's answer 是正确的,您必须创建第二个 groupby 对象,但您可以用更简单的方式计算百分比 - 只需 groupby state_office 并将 sales 列除以其和。复制 Paul H 答案的开头:

# From Paul H
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame('state': ['CA', 'WA', 'CO', 'AZ'] * 3,
                   'office_id': list(range(1, 7)) * 2,
                   'sales': [np.random.randint(100000, 999999)
                             for _ in range(12)])
state_office = df.groupby(['state', 'office_id']).agg('sales': 'sum')
# Change: groupby state_office and divide by sum
state_pcts = state_office.groupby(level=0).apply(lambda x:
                                                 100 * x / float(x.sum()))

返回:

                     sales
state office_id           
AZ    2          16.981365
      4          19.250033
      6          63.768601
CA    1          19.331879
      3          33.858747
      5          46.809373
CO    1          36.851857
      3          19.874290
      5          43.273852
WA    2          34.707233
      4          35.511259
      6          29.781508

【讨论】:

这是怎么回事?据我了解,x 是某种表格,所以100 * x 在直觉上没有意义(尤其是当某些单元格包含AZ 之类的字符串时,...)。 @dhardy state_office 是一个具有多索引的系列——所以它只是一个值都是数字的列。执行 groupby 后,每个 x 都是该列的子集。这有意义吗? 它可能,但它对我不起作用。 Python 3 中的 pandas 的工作方式是否有点不同? level=0 是什么意思? @Veenit 这意味着您是按索引的第一级分组,而不是按其中一个列。【参考方案2】:

您需要创建第二个按状态分组的 groupby 对象,然后使用 div 方法:

import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame('state': ['CA', 'WA', 'CO', 'AZ'] * 3,
               'office_id': list(range(1, 7)) * 2,
               'sales': [np.random.randint(100000, 999999) for _ in range(12)])

state_office = df.groupby(['state', 'office_id']).agg('sales': 'sum')
state = df.groupby(['state']).agg('sales': 'sum')
state_office.div(state, level='state') * 100


                     sales
state office_id           
AZ    2          16.981365
      4          19.250033
      6          63.768601
CA    1          19.331879
      3          33.858747
      5          46.809373
CO    1          36.851857
      3          19.874290
      5          43.273852
WA    2          34.707233
      4          35.511259
      6          29.781508

div 中的 level='state' kwarg 告诉 pandas 根据索引的 state 级别中的值广播/加入数据帧。

【讨论】:

如果您有 3 个索引,此方法是否有效?我首先在 3 列上进行了 groupby。然后我只对 2 做了第二个 groupby 并计算总和。然后我尝试使用div,但使用level=["index1", "index2"],但它告诉我Join on level between two MultiIndex objects is ambiguous @Ger 它确实有效,但我无法从该描述中猜出你做错了什么。多在网站上搜索一下。如果您没有找到任何东西,请使用可重现的示例创建一个新问题来演示该问题。 ***.com/questions/20109391/…【参考方案3】:

(这个解决方案的灵感来自这篇文章https://pbpython.com/pandas_transform.html

我发现以下使用transformation 的解决方案是最简单的(可能也是最快的):

转换:虽然聚合必须返回简化版本的 数据,转换可以返回完整的一些转换版本 数据重组。对于这样的转换,输出是相同的 形状作为输入。

所以使用transformation,解决方案是1-liner:

df['%'] = 100 * df['sales'] / df.groupby('state')['sales'].transform('sum')

如果你打印:

print(df.sort_values(['state', 'office_id']).reset_index(drop=True))

   state  office_id   sales          %
0     AZ          2  195197   9.844309
1     AZ          4  877890  44.274352
2     AZ          6  909754  45.881339
3     CA          1  614752  50.415708
4     CA          3  395340  32.421767
5     CA          5  209274  17.162525
6     CO          1  549430  42.659629
7     CO          3  457514  35.522956
8     CO          5  280995  21.817415
9     WA          2  828238  35.696929
10    WA          4  719366  31.004563
11    WA          6  772590  33.298509

【讨论】:

@Cancer 这是我最喜欢的答案,因为它将 df 保持为 df(不转换为系列)并且仅添加 % 列。谢谢 这个答案的变体对我来说效果很好transform('max') 指向描述 transform() 的帖子的链接很棒。我认为这是一个比所选解决方案更好的解决方案,但需要学习转换(我认为这是一个优点:)【参考方案4】:

为了简洁起见,我会使用 SeriesGroupBy:

In [11]: c = df.groupby(['state', 'office_id'])['sales'].sum().rename("count")

In [12]: c
Out[12]:
state  office_id
AZ     2            925105
       4            592852
       6            362198
CA     1            819164
       3            743055
       5            292885
CO     1            525994
       3            338378
       5            490335
WA     2            623380
       4            441560
       6            451428
Name: count, dtype: int64

In [13]: c / c.groupby(level=0).sum()
Out[13]:
state  office_id
AZ     2            0.492037
       4            0.315321
       6            0.192643
CA     1            0.441573
       3            0.400546
       5            0.157881
CO     1            0.388271
       3            0.249779
       5            0.361949
WA     2            0.411101
       4            0.291196
       6            0.297703
Name: count, dtype: float64

对于多个组,您必须使用转换(使用 Radical's df):

In [21]: c =  df.groupby(["Group 1","Group 2","Final Group"])["Numbers I want as percents"].sum().rename("count")

In [22]: c / c.groupby(level=[0, 1]).transform("sum")
Out[22]:
Group 1  Group 2  Final Group
AAHQ     BOSC     OWON           0.331006
                  TLAM           0.668994
         MQVF     BWSI           0.288961
                  FXZM           0.711039
         ODWV     NFCH           0.262395
...
Name: count, dtype: float64

这似乎比其他答案的性能略高(只是不到 Radical 答案速度的两倍,对我来说大约 0.08 秒)。

【讨论】:

这超级快。我会推荐这是首选的熊猫方法。真正利用了 numpy 的矢量化和 pandas 索引。 这对我也很有效,因为我正在与多个小组一起工作。谢谢。 对于多组,不使用transform也可以做到:c / c.groupby(level=[0, 1]).sum()【参考方案5】:

我认为这需要进行基准测试。使用OP的原始DataFrame,

df = pd.DataFrame(
    'state': ['CA', 'WA', 'CO', 'AZ'] * 3,
    'office_id': range(1, 7) * 2,
    'sales': [np.random.randint(100000, 999999) for _ in range(12)]
)

第一个Andy Hayden

正如他的回答所评论的那样,Andy 充分利用了矢量化和 pandas 索引。

c = df.groupby(['state', 'office_id'])['sales'].sum().rename("count")
c / c.groupby(level=0).sum()

3.42 毫秒 ± 16.7 µs 每个循环 (平均值±标准差。7 次运行,每次 100 次循环)


第二个Paul H

state_office = df.groupby(['state', 'office_id']).agg('sales': 'sum')
state = df.groupby(['state']).agg('sales': 'sum')
state_office.div(state, level='state') * 100

4.66 毫秒 ± 24.4 µs 每个循环 (平均值±标准差。7 次运行,每次 100 次循环)


第三个exp1orer

这是最慢的答案,因为它会为级别 0 中的每个 x 计算 x.sum()

对我来说,这仍然是一个有用的答案,尽管不是现在的形式。对于较小数据集的快速 EDA,apply 允许您使用 method chaining 将其写在一行中。因此,我们不再需要决定变量的名称,这实际上是您最宝贵的资源(您的大脑!!)的 computationally expensive。

这里是修改,

(
    df.groupby(['state', 'office_id'])
    .agg('sales': 'sum')
    .groupby(level=0)
    .apply(lambda x: 100 * x / float(x.sum()))
)

10.6 毫秒 ± 81.5 µs 每个循环 (平均值±标准差。7 次运行,每次 100 次循环)


所以没有人会关心小数据集上的 6 毫秒。但是,这是 3 倍的速度提升,并且在具有高基数 groupbys 的更大数据集上,这将产生巨大的影响。

添加到上面的代码中,我们制作了一个形状为 (12,000,000, 3) 的 DataFrame,其中包含 14412 个状态类别和 600 个 office_id,

import string

import numpy as np
import pandas as pd
np.random.seed(0)

groups = [
    ''.join(i) for i in zip(
    np.random.choice(np.array([i for i in string.ascii_lowercase]), 30000),
    np.random.choice(np.array([i for i in string.ascii_lowercase]), 30000),
    np.random.choice(np.array([i for i in string.ascii_lowercase]), 30000),
                       )
]

df = pd.DataFrame('state': groups * 400,
               'office_id': list(range(1, 601)) * 20000,
               'sales': [np.random.randint(100000, 999999)
                         for _ in range(12)] * 1000000
)

使用安迪,

2 秒 ± 10.4 毫秒/循环 (平均值±标准偏差。7 次运行,每次 1 个循环)

和探险家

19 秒 ± 77.1 毫秒/循环 (平均值±标准偏差。7 次运行,每次 1 个循环)

所以现在我们看到 x10 在大型、高基数数据集上加速。


如果你对这三个答案进行紫外线,请务必对这三个答案进行紫外线!!

【讨论】:

【参考方案6】:

我意识到这里已经有了很好的答案。

尽管如此,我还是想贡献自己的力量,因为我觉得对于这样一个基本的、简单的问题,应该有一个一眼就能理解的简短解决方案。

它还应该以一种我可以将百分比添加为新列的方式工作,而数据框的其余部分保持不变。最后但同样重要的是,它应该以一种明显的方式推广到有多个分组级别的情况(例如,州和国家,而不是只有州)。

以下 sn-p 满足这些条件:

df['sales_ratio'] = df.groupby(['state'])['sales'].transform(lambda x: x/x.sum())

请注意,如果您仍在使用 Python 2,则必须将 lambda 项的分母中的 x 替换为 float(x)。

【讨论】:

这是 IMO 的最佳答案。唯一要添加的是* 100 以使其成为百分比。 @Bouncner:是的,严格来说,您必须乘以 100 才能获得百分比——或者将新变量从“sales_percentage”重命名为“sales_ratio”。就个人而言,我更喜欢后者,并相应地编辑了答案。感谢提及! 如果你有多个级别,这不起作用。 @irene:好点,谢谢!可能在那种情况下 df.reset_index().groupby(['state'])['sales'].transform(lambda x: x/x.sum()) 会起作用。还是我忽略了什么? 这个答案很棒。它不涉及创建一个临时的groupby 对象,非常简洁,从左到右读起来非常合乎逻辑。【参考方案7】:

我知道这是一个老问题,但exp1orer's 对于具有大量唯一组的数据集(可能是因为 lambda)的回答非常慢。我根据他们的答案将其转换为数组计算,所以现在它超级快!下面是示例代码:

创建包含 50,000 个唯一组的测试数据框

import random
import string
import pandas as pd
import numpy as np
np.random.seed(0)

# This is the total number of groups to be created
NumberOfGroups = 50000

# Create a lot of groups (random strings of 4 letters)
Group1     = [''.join(random.choice(string.ascii_uppercase) for _ in range(4)) for x in range(NumberOfGroups/10)]*10
Group2     = [''.join(random.choice(string.ascii_uppercase) for _ in range(4)) for x in range(NumberOfGroups/2)]*2
FinalGroup = [''.join(random.choice(string.ascii_uppercase) for _ in range(4)) for x in range(NumberOfGroups)]

# Make the numbers
NumbersForPercents = [np.random.randint(100, 999) for _ in range(NumberOfGroups)]

# Make the dataframe
df = pd.DataFrame('Group 1': Group1,
                   'Group 2': Group2,
                   'Final Group': FinalGroup,
                   'Numbers I want as percents': NumbersForPercents)

分组后的样子:

                             Numbers I want as percents
Group 1 Group 2 Final Group                            
AAAH    AQYR    RMCH                                847
                XDCL                                182
        DQGO    ALVF                                132
                AVPH                                894
        OVGH    NVOO                                650
                VKQP                                857
        VNLY    HYFW                                884
                MOYH                                469
        XOOC    GIDS                                168
                HTOY                                544
AACE    HNXU    RAXK                                243
                YZNK                                750
        NOYI    NYGC                                399
                ZYCI                                614
        QKGK    CRLF                                520
                UXNA                                970
        TXAR    MLNB                                356
                NMFJ                                904
        VQYG    NPON                                504
                QPKQ                                948
...
[50000 rows x 1 columns]

数组求百分比方法:

# Initial grouping (basically a sorted version of df)
PreGroupby_df = df.groupby(["Group 1","Group 2","Final Group"]).agg('Numbers I want as percents': 'sum').reset_index()
# Get the sum of values for the "final group", append "_Sum" to it's column name, and change it into a dataframe (.reset_index)
SumGroup_df = df.groupby(["Group 1","Group 2"]).agg('Numbers I want as percents': 'sum').add_suffix('_Sum').reset_index()
# Merge the two dataframes
Percents_df = pd.merge(PreGroupby_df, SumGroup_df)
# Divide the two columns
Percents_df["Percent of Final Group"] = Percents_df["Numbers I want as percents"] / Percents_df["Numbers I want as percents_Sum"] * 100
# Drop the extra _Sum column
Percents_df.drop(["Numbers I want as percents_Sum"], inplace=True, axis=1)

此方法大约需要 ~0.15 秒

最佳答案法(使用 lambda 函数):

state_office = df.groupby(['Group 1','Group 2','Final Group']).agg('Numbers I want as percents': 'sum')
state_pcts = state_office.groupby(level=['Group 1','Group 2']).apply(lambda x: 100 * x / float(x.sum()))

此方法需要大约 21 秒才能产生相同的结果。

结果:

      Group 1 Group 2 Final Group  Numbers I want as percents  Percent of Final Group
0        AAAH    AQYR        RMCH                         847               82.312925
1        AAAH    AQYR        XDCL                         182               17.687075
2        AAAH    DQGO        ALVF                         132               12.865497
3        AAAH    DQGO        AVPH                         894               87.134503
4        AAAH    OVGH        NVOO                         650               43.132050
5        AAAH    OVGH        VKQP                         857               56.867950
6        AAAH    VNLY        HYFW                         884               65.336290
7        AAAH    VNLY        MOYH                         469               34.663710
8        AAAH    XOOC        GIDS                         168               23.595506
9        AAAH    XOOC        HTOY                         544               76.404494

【讨论】:

【参考方案8】:

在列或索引之间查找百分比的最优雅方法是使用pd.crosstab

样本数据

df = pd.DataFrame('state': ['CA', 'WA', 'CO', 'AZ'] * 3,
               'office_id': list(range(1, 7)) * 2,
               'sales': [np.random.randint(100000, 999999) for _ in range(12)])

输出数据框是这样的

print(df)

        state   office_id   sales
    0   CA  1   764505
    1   WA  2   313980
    2   CO  3   558645
    3   AZ  4   883433
    4   CA  5   301244
    5   WA  6   752009
    6   CO  1   457208
    7   AZ  2   259657
    8   CA  3   584471
    9   WA  4   122358
    10  CO  5   721845
    11  AZ  6   136928

只需指定要聚合的索引、列和值。 normalize 关键字将根据上下文计算跨索引或列的百分比。

result = pd.crosstab(index=df['state'], 
                     columns=df['office_id'], 
                     values=df['sales'], 
                     aggfunc='sum', 
                     normalize='index').applymap(':.2f%'.format)




print(result)
office_id   1   2   3   4   5   6
state                       
AZ  0.00%   0.20%   0.00%   0.69%   0.00%   0.11%
CA  0.46%   0.00%   0.35%   0.00%   0.18%   0.00%
CO  0.26%   0.00%   0.32%   0.00%   0.42%   0.00%
WA  0.00%   0.26%   0.00%   0.10%   0.00%   0.63%

【讨论】:

【参考方案9】:

您可以将sum 整个DataFrame 除以state 总数:

# Copying setup from Paul H answer
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame('state': ['CA', 'WA', 'CO', 'AZ'] * 3,
               'office_id': list(range(1, 7)) * 2,
               'sales': [np.random.randint(100000, 999999) for _ in range(12)])
# Add a column with the sales divided by state total sales.
df['sales_ratio'] = (df / df.groupby(['state']).transform(sum))['sales']

df

返回

    office_id   sales state  sales_ratio
0           1  405711    CA     0.193319
1           2  535829    WA     0.347072
2           3  217952    CO     0.198743
3           4  252315    AZ     0.192500
4           5  982371    CA     0.468094
5           6  459783    WA     0.297815
6           1  404137    CO     0.368519
7           2  222579    AZ     0.169814
8           3  710581    CA     0.338587
9           4  548242    WA     0.355113
10          5  474564    CO     0.432739
11          6  835831    AZ     0.637686

但请注意,这仅适用于除 state 之外的所有列都是数字的,从而可以对整个 DataFrame 求和。例如,如果 office_id 是字符,则会出现错误:

df.office_id = df.office_id.astype(str)
df['sales_ratio'] = (df / df.groupby(['state']).transform(sum))['sales']

TypeError: /: 'str' 和 'str' 的操作数类型不受支持

【讨论】:

我编辑指出,这仅适用于除groupby 列之外的所有列都是数字的情况。但它在其他方面非常优雅。有没有办法让它与其他 str 列一起使用? 据我所知:***.com/questions/34099684/…【参考方案10】:
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame('state': ['CA', 'WA', 'CO', 'AZ'] * 3,
               'office_id': list(range(1, 7)) * 2,
               'sales': [np.random.randint(100000, 999999) for _ in range(12)])

df.groupby(['state', 'office_id'])['sales'].sum().rename("weightage").groupby(level = 0).transform(lambda x: x/x.sum())
df.reset_index()

输出:

    state   office_id   weightage
0   AZ  2   0.169814
1   AZ  4   0.192500
2   AZ  6   0.637686
3   CA  1   0.193319
4   CA  3   0.338587
5   CA  5   0.468094
6   CO  1   0.368519
7   CO  3   0.198743
8   CO  5   0.432739
9   WA  2   0.347072
10  WA  4   0.355113
11  WA  6   0.297815

【讨论】:

【参考方案11】:

我认为这可以在 1 行中解决问题:

df.groupby(['state', 'office_id']).sum().transform(lambda x: x/np.sum(x)*100)

【讨论】:

我相信它会占用数据集的所有列。在这种情况下,只有一个。如果您有多个并且想要对单个执行此操作,只需在 groupby 表达式之后指定它: df.groupby(['state', 'office_id'])[[YOUR COLUMN NAME HERE]].etc 如果需要为了保持其他列不变,只需重新分配特定列 @louisD:我非常喜欢你试图保持简短的方法。不幸的是,当我尝试按照您的建议重新分配列时,出现两个错误:“ValueError: Buffer dtype mismatch, expected 'Python object' but got 'long long'”,另外(在处理第一个异常期间):“ TypeError:插入列的索引与框架索引不兼容”我使用的代码如下:df['percent'] = df.groupby(['state', 'office_id']).sum().transform(lambda x: x/np.sum(x)*100) 因此,我将发布一个单独的答案来解决这个问题。【参考方案12】:

我使用的简单方法是在 2 个 groupby 之后进行合并,然后进行简单除法。

import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame('state': ['CA', 'WA', 'CO', 'AZ'] * 3,
               'office_id': list(range(1, 7)) * 2,
               'sales': [np.random.randint(100000, 999999) for _ in range(12)])

state_office = df.groupby(['state', 'office_id'])['sales'].sum().reset_index()
state = df.groupby(['state'])['sales'].sum().reset_index()
state_office = state_office.merge(state, left_on='state', right_on ='state', how = 'left')
state_office['sales_ratio'] = 100*(state_office['sales_x']/state_office['sales_y'])

   state  office_id  sales_x  sales_y  sales_ratio
0     AZ          2   222579  1310725    16.981365
1     AZ          4   252315  1310725    19.250033
2     AZ          6   835831  1310725    63.768601
3     CA          1   405711  2098663    19.331879
4     CA          3   710581  2098663    33.858747
5     CA          5   982371  2098663    46.809373
6     CO          1   404137  1096653    36.851857
7     CO          3   217952  1096653    19.874290
8     CO          5   474564  1096653    43.273852
9     WA          2   535829  1543854    34.707233
10    WA          4   548242  1543854    35.511259
11    WA          6   459783  1543854    29.781508

【讨论】:

【参考方案13】:
df = pd.DataFrame('state': ['CA', 'WA', 'CO', 'AZ'] * 3,
               'office_id': list(range(1, 7)) * 2,
               'sales': [np.random.randint(100000, 999999)
                         for _ in range(12)])

grouped = df.groupby(['state', 'office_id'])
100*grouped.sum()/df[["state","sales"]].groupby('state').sum()

返回:

sales
state   office_id   
AZ  2   54.587910
    4   33.009225
    6   12.402865
CA  1   32.046582
    3   44.937684
    5   23.015735
CO  1   21.099989
    3   31.848658
    5   47.051353
WA  2   43.882790
    4   10.265275
    6   45.851935

【讨论】:

【参考方案14】:

作为一个也在学习 pandas 的人,我发现其他答案有点含蓄,因为 pandas 将大部分工作隐藏在幕后。即通过自动匹配列和索引名称来操作操作的工作方式。这段代码应该相当于@exp1orer接受的答案的逐步版本

对于df,我将使用别名state_office_sales 来称呼它:

                  sales
state office_id        
AZ    2          839507
      4          373917
      6          347225
CA    1          798585
      3          890850
      5          454423
CO    1          819975
      3          202969
      5          614011
WA    2          163942
      4          369858
      6          959285

state_total_salesstate_office_salesindex level 0(最左侧)中的总和分组。

In:   state_total_sales = df.groupby(level=0).sum()
      state_total_sales

Out: 
       sales
state   
AZ     2448009
CA     2832270
CO     1495486
WA     595859

因为两个数据框共享一个索引名和一个列名,所以 pandas 会通过共享索引找到合适的位置,例如:

In:   state_office_sales / state_total_sales

Out:  

                   sales
state   office_id   
AZ      2          0.448640
        4          0.125865
        6          0.425496
CA      1          0.288022
        3          0.322169
        5          0.389809
CO      1          0.206684
        3          0.357891
        5          0.435425
WA      2          0.321689
        4          0.346325
        6          0.331986

为了更好地说明这一点,这里是一个带有 XX 的部分总数,没有等价物。 Pandas 会根据索引和列名匹配位置,没有重叠的地方 pandas 会忽略它:

In:   partial_total = pd.DataFrame(
                      data   =  'sales' : [2448009, 595859, 99999],
                      index  =             ['AZ',    'WA',   'XX' ]
                      )
      partial_total.index.name = 'state'


Out:  
         sales
state
AZ       2448009
WA       595859
XX       99999
In:   state_office_sales / partial_total

Out: 
                   sales
state   office_id   
AZ      2          0.448640
        4          0.125865
        6          0.425496
CA      1          NaN
        3          NaN
        5          NaN
CO      1          NaN
        3          NaN
        5          NaN
WA      2          0.321689
        4          0.346325
        6          0.331986

当没有共享索引或列时,这一点变得非常清楚。这里missing_index_totals 等于state_total_sales,只是它没有索引名称。

In:   missing_index_totals = state_total_sales.rename_axis("")
      missing_index_totals

Out:  
       sales
AZ     2448009
CA     2832270
CO     1495486
WA     595859
In:   state_office_sales / missing_index_totals 

Out:  ValueError: cannot join with no overlapping index names

【讨论】:

【参考方案15】:

一线解决方案:

df.join(
    df.groupby('state').agg(state_total=('sales', 'sum')),
    on='state'
).eval('sales / state_total')

这会返回一系列每个办公室的比率——可以单独使用或分配给原始数据框。

【讨论】:

以上是关于使用 groupby 的 Pandas 占总数的百分比的主要内容,如果未能解决你的问题,请参考以下文章

pandas groupby 并为各自的总数聚合两列,然后计算比率 - 总结摘要

获取 Pandas 列的总数

百分比行占总数,其中每行由 group by 子句确定

pandas groupby中的自定义聚合函数

pandas 中的聚合和计数

使用 Groupby 的 Pandas 滚动函数