Pandas% от общего числа с groupby

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

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

  • лучший способ бросить нанки ряды в пандах
  • Копирование файлов данных MultiIndex с помощью pd.read_clipboard?
  • Есть ли функция pandas для отображения первых / последних n столбцов, как в .head () & .tail ()?
  • reindex для добавления отсутствующих дат в pandas dataframe
  • Эффективно выберите строки, которые соответствуют одному из нескольких значений в Pandas DataFrame
  • Проверьте, находится ли строка в кадре данных pandas
  • Я хочу рассчитать процент продаж на офис в определенном состоянии (общее количество всех процентов в каждом штате составляет 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 для вычисления доли.

  • Не удается заставить Elasticsearch работать с Django
  • Настройка промежуточного ПО прокси-сервера Scrapy для поворота по каждому запросу
  • Как создать яйца Python из исходных пакетов distutils?
  • почему определены «__new__» и «__init__» все в классе
  • Ткань запрашивает пароль, хотя я могу использовать SSH с учетными данными
  • Формат плавает со стандартным модулем json
  • 4 Solutions collect form web for “Pandas% от общего числа с groupby”

    Пол Х ответил правильно, что вам придется сделать второй объект groupby , но вы можете рассчитать процент проще, просто groupby по state_office и state_office столбец sales на его сумму. Копирование начала ответа Пола Х:

     # 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 

    Вам нужно сделать второй объект 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 сообщает pandas передавать / присоединяться к базе данных dataframes по значениям на уровне состояния индекса.

    Вы можете sum весь DataFrame и делить на общую сумму:

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

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

    Создайте тестовый фрейм с 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 
    Python - лучший язык программирования в мире.