Відсоток панди від загальної групи


148

Це, очевидно, просто, але, як онімілий новач, я застрягаю.

У мене є файл CSV, який містить 3 стовпці, штат, ідентифікатор Office та продажі для цього офісу.

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


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

1
Що тут відбувається? Як я розумію, xце таблиця якоїсь подібної форми, тому 100 * xвона не має сенсу інтуїтивно (особливо, коли деякі комірки містять рядки, наприклад AZ, ...).
безтурботний

5
@dhardy state_office- це серія з множинним індексом, тож це лише один стовпець, значення якого всі числові. Після того як ви зробите groupby, кожен x- це підмножина цього стовпця. Чи має це сенс?
exp1orer

2
Це може, але це не спрацювало для мене. Чи працюють панди в Python 3 дещо інакше?
безтурботний

1
Що level=0означає?
van_d39

3
@Veenit це означає, що ви групуєтесь за першим рівнем індексу, а не за одним із стовпців.
exp1orer

54

Вам потрібно створити другий об'єкт групи, який групується за станами, а потім скористатися 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 Це дійсно працює, але немає ніякого способу, як я міг би заробити те, що ви робите неправильно з цього опису. Шукайте по сайту трохи більше. Якщо ви нічого не знайдете, створіть нове запитання з відтворюваним прикладом, який демонструє проблему. 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

Для декількох груп ви повинні використовувати перетворення (використовуючи df Radical ):

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 петлі кожен)

Отже, зараз ми бачимо швидкість x10 на великих, високих наборах даних про кардинальність.


Будьте впевнені, щоб УФ ці три відповіді, якщо ви УФ цей !!


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 дуже повільна для наборів даних з великою кількістю унікальних груп (можливо, через лямбда). Я створив їх відповідь, щоб перетворити його на обчислення масиву, тому зараз це дуже швидко! Нижче наведено приклад коду:

Створіть тестовий кадр даних із 50000 унікальних груп

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, вам доведеться замінити х у знаменнику лямбда-терміна на float (x).


Це найкраща відповідь ІМО. Єдине, що слід додати, було б * 100зробити це у відсотках.
Bouncner

1
@Bouncner: Так, строго кажучи, вам доведеться помножити на 100, щоб отримати відсоток - або перейменувати нову змінну з "sales_percentage" на "sales_ratio". Особисто я віддаю перевагу останньому, і відповідь я редагував відповідно. Дякуємо за згадування!
MightyCurious

2
Це не працює, якщо у вас є кілька рівнів.
Ірен

@irene: Добрий момент, дякую! Можливо, у цьому випадку df.reset_index (). Groupby (['стан']) ['продажі']. Трансформація (лямбда x: x / x.sum ()) спрацює. Або я щось переглядаю?
MightyCurious

1
Ця відповідь чудова. Це не передбачає створення тимчасового groupbyоб'єкта, є надто стислим і читається дуже логічно зліва направо.
C. Braun

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

Просто вкажіть індекс, стовпці та значення для агрегування. Ключове слово "нормалізація" буде обчислювати% по індексу або стовпцям залежно від контексту.

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%

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']

TypeError: непідтримувані типи операндів для /: 'str' та 'str'


Я відредагував, щоб зазначити, що це працює лише тоді, коли всі стовпці, крім groupbyстовпця, є числовими. Але це інакше досить елегантно. Чи є спосіб змусити його працювати з іншими strстовпцями?
Макс Ghenis

Не наскільки я знаю: stackoverflow.com/questions/34099684/…
iggy

2

Я думаю, що це зробить трюк в 1 рядок:

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

Я вважаю, що він займає всі стовпці набору даних. у цьому випадку є лише один. Якщо у вас є декілька, і ви хочете виконати цю операцію на синглі, просто вкажіть її після виразу groupby: df.groupby (['стан', 'office_id']) [[ВАШ ІМЕННЕ КОЛІНУ ТУТ]]. Etcetc, якщо ви хочете щоб залишити інші стовпці недоторканими, просто перепризначили конкретні стовпці
louisD

@louisD: Мені дуже подобається ваш підхід до спроби зробити його коротким. На жаль, коли я намагаюся перепризначити стовпець так, як ви запропонували, я отримую дві помилки: "ValueError: Невідповідність типу буфера, очікуваний" об'єкт Python ", але отриманий" довгий довгий "", і додатково (під час обробки першого винятку): " TypeError: несумісний індекс вставленого стовпця з індексом кадру "Код, який я використав, був такий: df ['відсоток"] = df.groupby ([' стан ',' office_id ']). Sum (). Перетворення (лямбда x: x / np.sum (x) * 100) Тому я опублікую окрему відповідь, щоб виправити це.
Могутній лютий

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

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

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')

Це повертає Серію співвідношень на офіс - може використовуватися самостійно або призначатися оригінальному Dataframe.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.