Процент панд от общего с групповым

148

Это очевидно просто, но как новичок я застрял.

У меня есть CSV-файл, который содержит 3 столбца: штат, идентификатор офиса и продажи для этого офиса.

Я хочу рассчитать процент продаж на офис в данном состоянии (общее количество всех процентов в каждом штате составляет 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

Кажется, я не могу понять, как «дотянуться» до stateуровня, groupbyчтобы подвести итог salesдля всего, stateчтобы вычислить долю.

erikcw
источник
3
df['sales'] / df.groupby('state')['sales'].transform('sum')кажется, самый ясный ответ.
Поль Ружье

Ответы:

207

Ответ Павла Эйч это правильно , что вы должны сделать второй groupbyобъект, но вы можете вычислить процент более простым способом - просто и разделить колонку по ее сумме. Копирование начала ответа Пола Х:groupbystate_officesales

# 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
exp1orer
источник
1
Что тут происходит? Насколько я понимаю, xэто какая-то таблица, поэтому 100 * xона не имеет смысла (особенно когда некоторые ячейки содержат строки типа AZ...).
Дарди
5
@dhardy state_office- это серия с мультииндексом, так что это всего лишь один столбец, все значения которого являются числовыми. После того, как вы выполните групповую работу, каждый xявляется подмножеством этого столбца. Имеет ли это смысл?
exp1orer
2
Возможно, но это не сработало для меня. Панды в Python 3 работают немного по-другому?
Дарди
1
Что level=0значит?
van_d39
3
@Veenit означает, что вы группируете по первому уровню индекса, а не по одному из столбцов.
exp1orer
54

Вам нужно создать второй объект 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

level='state'kwarg в divговорит панд широковещательного / присоединиться к базе dataframes на значения в stateуровне индекса.

Пол Х
источник
4
Этот метод работает, если у вас есть 3 индекса? Сначала я сделал групповой на 3 колонки. Затем я сделал вторую группу только на 2 и вычислил сумму. Затем я пытаюсь использовать, divно с, level=["index1", "index2"]но это говорит мне об этом Join on level between two MultiIndex objects is ambiguous.
Ger
@Ger Это работает, но я никак не могу предугадать, что ты делаешь неправильно из этого описания. Ищите на сайте немного больше. Если вы ничего не нашли, создайте новый вопрос с воспроизводимым примером, который демонстрирует проблему. stackoverflow.com/questions/20109391/…
Пол Х
34

Для краткости я бы использовал 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

Для нескольких групп вы должны использовать transform (используя 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

Похоже, что это немного более эффективно, чем другие ответы (чуть менее, чем в два раза быстрее ответа Радикала, для меня ~ 0,08 с).

Энди Хейден
источник
5
Это супер быстро. Я рекомендовал бы это как предпочтительный подход панд. Действительно использует векторизацию numpy и индексацию панд.
Чарльз
Это хорошо сработало и для меня, так как я работаю с несколькими группами. Спасибо.
Ирэн
27

Я думаю, что это требует сравнительного анализа. Используя оригинальный DataFrame OP,

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

1-й Энди Хейден

Как прокомментировал его ответ, Энди в полной мере использует векторизацию и индексацию панд.

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

3,42 мс ± 16,7 мкс на цикл
(среднее ± стандартное отклонение из 7 циклов, по 100 циклов в каждом)


2-й Пол Н

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 мкс на цикл
(среднее ± стандартное отклонение из 7 циклов, по 100 циклов в каждом)


3-й exp1orer

Это самый медленный ответ, так как он рассчитывается x.sum()для каждого xна уровне 0.

Для меня это все еще полезный ответ, хотя и не в его нынешнем виде. Для быстрого EDA для небольших наборов данных applyпозволяет использовать цепочку методов, чтобы записать это в одну строку. Поэтому мы убираем необходимость выбора имени переменной, которая на самом деле очень затратна в вычислительном отношении для вашего самого ценного ресурса (вашего мозга !!).

Вот модификация,

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

10,6 мс ± 81,5 мкс на цикл
(среднее ± стандартное отклонение из 7 циклов, по 100 циклов в каждом)


Таким образом, никто не собирается заботиться о 6 мс на небольшом наборе данных. Тем не менее, это в 3 раза быстрее, и для больших наборов данных с большим количеством групповых пользователей это будет иметь огромное значение.

В дополнение к приведенному выше коду мы создаем DataFrame с формой (12 000 000, 3) с 14412 категориями состояний и 600 office_ids,

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 циклу каждый)

и exp1orer

19 с ± 77,1 мс на цикл
(среднее ± стандартное отклонение из 7 циклов, по 1 циклу каждый)

Так что теперь мы видим ускорение в 10 раз на больших наборах данных с большим количеством элементов.


Обязательно УФ эти три ответа, если вы УФ этот !!

Маленькие Бобби Столы
источник
17

(Это решение вдохновлено этой статьей https://pbpython.com/pandas_transform.html )

Я считаю, что следующее решение является самым простым (и, вероятно, самым быстрым) при использовании transformation:

Преобразование. Хотя агрегация должна возвращать сокращенную версию данных, преобразование может возвращать некоторую преобразованную версию полных данных для рекомбинации. Для такого преобразования выходные данные имеют ту же форму, что и входные.

Таким образом, используя transformationрешение, 1-лайнер:

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
Джанер
источник
3
@Cancer Это мой любимый ответ, поскольку он сохраняет df как df (без преобразования в серии) и просто добавляет столбец%. Спасибо
T.Fung
Вариация этого ответа очень хорошо сработала для меняtransform('max')
Шелдор
11

Я знаю, что это старый вопрос, но ответ exp1orer очень медленный для наборов данных с большим количеством уникальных групп (вероятно, из-за лямбды). Я построил их ответ, чтобы превратить его в вычисление массива, так что теперь это очень быстро! Ниже приведен пример кода:

Создайте тестовый фрейм с 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 секунд

Метод верхнего ответа (с использованием лямбда-функции):

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
Радикальный Эдвард
источник
9

Я понимаю, что здесь уже есть хорошие ответы.

Я, тем не менее, хотел бы внести свой вклад, потому что я чувствую к простому, простому вопросу, как этот, должно быть краткое решение, которое понятно с первого взгляда.

Он также должен работать таким образом, чтобы я мог добавить проценты в качестве нового столбца, оставив остальную часть кадра данных нетронутой. И последнее, но не менее важное: оно должно обобщаться очевидным образом на случай, когда существует более одного уровня группировки (например, штат и страна, а не только штат).

Следующий фрагмент кода соответствует этим критериям:

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

Обратите внимание, что если вы все еще используете Python 2, вам придется заменить x в знаменателе лямбда-термина на float (x).

MightyCurious
источник
Это лучший ответ ИМО. Единственное, что нужно добавить, это * 100сделать процент.
Bouncner
1
@Bouncner: Да, строго говоря, вам придется умножить на 100, чтобы получить процент - или переименовать новую переменную из «sales_percentage» в «sales_ratio». Лично я предпочитаю последнее, и я отредактировал ответ соответственно. Спасибо за упоминание!
MightyCurious
2
Это не работает, если у вас есть несколько уровней.
Ирэн
@irene: Хорошо, спасибо! Вероятно, в этом случае будет работать df.reset_index (). Groupby (['state']) ['sales']. Transform (lambda x: x / x.sum ()). Или я что-то упускаю?
MightyCurious
1
Этот ответ великолепен. Он не включает создание временного groupbyобъекта, является очень кратким и очень логично читает слева направо.
С. Браун
7

Самый элегантный способ найти проценты по столбцам или индексам - использовать 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%
ajknzhol
источник
3

Вы можете 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']

Ошибка типа: неподдерживаемые типы операндов для /: 'str' и 'str'

Iggy
источник
Я отредактировал, чтобы отметить, что это работает только тогда, когда все столбцы, кроме groupbyстолбца, являются числовыми. Но в остальном это довольно элегантно. Есть ли способ заставить его работать с другими strстолбцами?
Макс Генис
Не настолько, насколько я знаю: stackoverflow.com/questions/34099684/…
iggy
2

Я думаю, что это бы сработало в 1 строку:

df.groupby(['state', 'office_id']).sum().transform(lambda x: x/np.sum(x)*100)
louisD
источник
Я считаю, что это занимает все столбцы набора данных. в этом случае есть только один. Если у вас их несколько и вы хотите выполнить эту операцию для одного, просто укажите ее после выражения groupby: df.groupby (['state', 'office_id']) [[YOUR COLUMN NAME HERE]]. Etcetc, если хотите чтобы не
трогать
@LouisD: Мне очень нравится ваш подход, чтобы попытаться сделать это коротким. К сожалению, когда я пытаюсь переназначить столбец, как вы предложили, я получаю две ошибки: «ValueError: Несоответствие буфера dtype, ожидаемый« объект Python », но получил« long long »», и дополнительно (при обработке первого исключения): " TypeError: несовместимый индекс вставленного столбца с индексом фрейма "Я использовал следующий код: df ['процент'] = df.groupby (['state', 'office_id']). Sum (). Transform (lambda x: x / np.sum (x) * 100) Поэтому я выложу отдельный ответ, чтобы это исправить.
MightyCurious
1

Простой способ, которым я воспользовался, - это слияние после того, как 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
upliftedLemur
источник
1
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
Alessandro
источник
0

Как человек, который также изучает панд, я нашел другие ответы несколько неявными, поскольку панды скрывают большую часть работы за кулисами. А именно в том, как работает операция, автоматически сопоставляя имена столбцов и индексов. Этот код должен быть эквивалентен пошаговой версии принятого ответа @ 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_salesэто state_office_salesсгруппировано по общим суммам в index 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

Поскольку два фрейма данных совместно используют индексное имя и панды с именем столбца, они найдут подходящие местоположения через общие индексы, такие как:

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эквивалентом. Панды будут сопоставлять местоположение на основе имен индексов и столбцов, где нет перекрывающихся панд, будут игнорировать его:

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
Андерс Солберг
источник
-1

Однолинейное решение:

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

Это возвращает ряд коэффициентов для каждого офиса - может использоваться отдельно или назначаться исходному кадру данных.

ribitskiyb
источник