গোষ্ঠীর সাথে মোট পান্ডার শতাংশ percentage


147

এটি স্পষ্টতই সহজ, তবে একটি অদ্ভুত নতুন হিসাবে আমি আটকে যাচ্ছি।

আমার কাছে একটি সিএসভি ফাইল রয়েছে যাতে 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ভগ্নাংশ গণনা করা হবে।


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, যেমন ...)।
dhardy

5
@ ধরডি state_officeহ'ল একটি মাল্টি ইন্ডেক্স সহ একটি সিরিজ - সুতরাং এটি কেবলমাত্র একটি কলাম যার মানগুলি সমস্ত সংখ্যাসূচক। আপনি গ্রুপবাইয়ের পরে, প্রতিটি xহ'ল সেই কলামটির উপসেট। যে জানার জন্য?
exp1orer

2
এটি হতে পারে, তবে এটি আমার পক্ষে কার্যকর হয়নি। পাইথন 3 এর পান্ডগুলি কি কিছুটা আলাদাভাবে কাজ করে?
ধর্মি

1
কী level=0মানে?
ভ্যান_ডি 39

3
@ ভিউনিট এর অর্থ হ'ল আপনি কলামগুলির মধ্যে একটির চেয়ে সূচকের প্রথম স্তরের সাথে গ্রুপিং করছেন।
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
জের

@ জের এটি কাজ করে, তবে আপনি যে বর্ণনাটি থেকে ভুল করছেন তা আমি প্রকাশ করার কোন উপায় নেই। সাইটে আরও কিছুটা অনুসন্ধান করুন। যদি আপনি কিছু না পান তবে একটি পুনরুত্পাদনযোগ্য উদাহরণ দিয়ে একটি নতুন প্রশ্ন তৈরি করুন যা সমস্যাটি দেখায়। stackoverflow.com/questions/20109391/…
পল এইচ

34

সংক্ষিপ্ততার জন্য আমি সিরিজ গ্রুপটি ব্যবহার করব:

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

একাধিক গোষ্ঠীর জন্য আপনাকে ট্রান্সফর্ম ব্যবহার করতে হবে ( র্যাডিকালের ডিএফ ব্যবহার করে ):

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

এটি অন্যান্য উত্তরের তুলনায় কিছুটা বেশি পারফরম্যান্ট বলে মনে হচ্ছে (আমার পক্ষে র‌্যাডিকাল জবাবের গতির দ্বিগুণের চেয়ে কম)।


5
এটি সুপার দ্রুত। আমি এটি পছন্দসই পান্ডাস পদ্ধতির হিসাবে সুপারিশ করব। সত্যিই নম্পির ভেক্টরাইজেশন এবং পান্ডাস সূচকের সুবিধা গ্রহণ করে।
চার্লস

এটি আমার পক্ষেও বেশ ভাল কাজ করেছে, কারণ আমি একাধিক গ্রুপের সাথে কাজ করছি। ধন্যবাদ।
আয়রিন

27

আমি মনে করি এটির জন্য বেঞ্চমার্কিং দরকার। ওপির আসল ডেটা ফ্রেম ব্যবহার করে,

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 of রানের গড় ± স্ট্যান্ড। ডিভ। প্রতি 100 টি লুপ)


২ য় পল এইচ

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 এমএস .4 24.4
(গুলি (7 7 রানের গড় ± দশমিক দেব, প্রতিটি 100 লুপ)


3 য় এক্সপোর 1

এটি স্তরের 0 হিসাবে x.sum()প্রতিটি হিসাবে গণনা করা এটি সবচেয়ে ধীর উত্তর x

আমার জন্য, এটি এখনও একটি দরকারী উত্তর, যদিও এটি বর্তমান আকারে নেই। ছোট ডেটাসেটে দ্রুত ইডিএর জন্য, applyআপনাকে একক লাইনে এটি লেখার জন্য চেইন পদ্ধতি ব্যবহার করতে দেয় method অতএব আমরা কোনও ভেরিয়েবলের নামের সিদ্ধান্ত নেওয়ার প্রয়োজনটি সরিয়ে ফেলি, যা আসলে খুব বেশি আপনার অত্যন্ত মূল্যবান সংস্থান (আপনার মস্তিষ্ক !!) এর জন্য কম্পিউটেশনাল ব্যয়বহুল

এখানে পরিবর্তন আছে,

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

10.6 এমএস ± 81.5 µ গুলি প্রতি লুপ
(অর্থাত্ runs± রানের গড় dev৫ রান, প্রতিটি ১০০ টি লুপ)


সুতরাং কেউ একটি ছোট ডেটাসেটের 6ms সম্পর্কে যত্ন করে না। যাইহোক, এটি 3x গতি এবং উচ্চ কার্ডিনালিটি গ্রুপবাইয়ের সাথে একটি বৃহত্তর ডেটাসেটে এটি একটি বিশাল পার্থক্য আনতে চলেছে।

উপরের কোডটিতে যুক্ত করে আমরা 14412 রাষ্ট্র বিভাগ এবং 600 অফিস_আইডস সহ আকৃতির (12,000,000, 3) সহ একটি ডেটা ফ্রেম তৈরি করি,

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 এমএস প্রতি লুপ
(মানে ± স্ট্যান্ড। Dev রানের ডেভেল, প্রতিটি লুপ প্রতিটি)

এবং exp1orer

লুপ প্রতি 19 এস ± 77.1 এমএস
(7 of রানের গড় ± স্ট্যান্ডার্ড। প্রতিটি লুপ প্রতিটি)

সুতরাং এখন আমরা বড়, উচ্চ কার্ডিনালিটি ডেটাসেটগুলিতে এক্স 10 গতি বাড়িয়ে দেখছি।


আপনি যদি এই একটিকে ইউভি করেন তবে এই তিনটি উত্তরকে অবশ্যই ইউভি নিশ্চিত করুন!


16

(এই সমাধানটি এই নিবন্ধটি থেকে অনুপ্রাণিত 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

2
@ ক্যান্সার এটি আমার পছন্দসই উত্তর কারণ এটি ডিএফকে ডিএফ হিসাবে রাখে (সিরিজে রূপান্তর না করে) এবং কেবল একটি% কলাম যুক্ত করে। আপনাকে ধন্যবাদ
টিফুং

এই উত্তরটির transform('max')
প্রকরণটি

11

আমি জানি যে এটি একটি পুরানো প্রশ্ন, তবে এক্সপোসিওরর উত্তরটি বিশাল সংখ্যক অনন্য গোষ্ঠী (সম্ভবত ল্যাম্বডার কারণে) সহ ডেটাসেটগুলির জন্য খুব ধীর। এটিকে একটি অ্যারে গণনায় পরিণত করার জন্য আমি তাদের উত্তরটি বন্ধ করে দিয়েছি তাই এখন এটি সুপার দ্রুত! নীচে উদাহরণ কোড দেওয়া হল:

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

মনে রাখবেন যে আপনি যদি এখনও পাইথন 2 ব্যবহার করে থাকেন তবে আপনাকে ল্যাম্বা শব্দটির ডিনোমিনেটরে x টি ফ্লোট (x) দ্বারা প্রতিস্থাপন করতে হবে।


এটি সেরা উত্তর আইএমও। এটি যুক্ত * 100করার জন্য কেবল জিনিসটিই এটি শতাংশ করতে হবে।
বাউঙ্কার

1
@ বাউনার: হ্যাঁ, কঠোরভাবে বলতে গেলে আপনাকে শতকরা পেতে ১০০ দিয়ে গুণ করতে হবে - বা নতুন বিক্রয়কটির নাম "বিক্রয়_পরিবর্তন" থেকে "বিক্রয়_আরটিও" করতে হবে। ব্যক্তিগতভাবে, আমি উত্তরোত্তর পছন্দ করি এবং আমি সেই অনুযায়ী উত্তরটি সম্পাদনা করি। উল্লেখ করার জন্য ধন্যবাদ!
মাইক্রিটিকিয়াস

2
আপনার একাধিক স্তর থাকলেও এটি কাজ করে না।
আয়রনে

@ আয়রিন: ভাল কথা, ধন্যবাদ! সম্ভবত সেক্ষেত্রে df.reset_index ()। Groupby (['state']] ['বিক্রয়']। রূপান্তর (ল্যাম্বডা এক্স: এক্স / এক্স.সাম ()) কাজ করবে work নাকি আমি কিছু উপেক্ষা করছি?
মাইক্রিটিকিয়াস

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

সামগ্রিকভাবে সূচক, কলাম এবং মানগুলি নির্দিষ্ট করুন। নরমালাইজ কীওয়ার্ড প্রসঙ্গের উপর নির্ভর করে সূচক বা কলামগুলিতে% গণনা করবে।

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সংখ্যাসূচক, পুরো ডেটা ফ্রেমের সংশ্লেষ সক্ষম করে। উদাহরণস্বরূপ, 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কলামগুলির সাথে কাজ করার কোনও উপায় আছে ?
ম্যাক্স ঘেনিস


2

আমি মনে করি এটি 1 টি লাইনে কৌশলটি করবে:

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

আমি বিশ্বাস করি এটি ডেটাসেটের সমস্ত কলাম নেয়। এই ক্ষেত্রে, শুধুমাত্র একটি আছে। যদি আপনার বেশ কয়েকটি থাকে এবং কোনও গতিবেগ নিয়ে এই অপারেশনটি সম্পাদন করতে চান, তবে কেবল গ্রুপবাইয়ের অভিব্যক্তির পরে এটি নির্দিষ্ট করুন: df.groupby (['রাজ্য', 'অফিস_আইডি']) [[আপনার রঙ নাম এখানে]]। অন্যান্য কলামগুলিকে
নিরবচ্ছিন্ন

@ লুইসডি: এটি সংক্ষিপ্ত রাখার চেষ্টা করার আপনার দৃষ্টিভঙ্গিটি আমি খুব পছন্দ করি। দুর্ভাগ্যক্রমে, যখন আমি আপনার পরামর্শ অনুসারে কলামটি পুনরায় নিয়োগের চেষ্টা করব তখন আমি দুটি ত্রুটি পেয়েছি: "ভ্যালু এরির: বাফার টাইপ মিল নেই, প্রত্যাশিত 'পাইথন অবজেক্ট' তবে 'দীর্ঘ দীর্ঘ' 'পেয়েছে, এবং অতিরিক্তভাবে (প্রথম ব্যতিক্রম পরিচালনা করার সময়):" প্রকারের ত্রুটি: ফ্রেম সূচক সহ columnোকানো কলামের বেমানান সূচক "আমি যে কোডটি ব্যবহার করেছি তা নিম্নলিখিত: df ['শতাংশ'] = df.groupby (['রাষ্ট্র', 'অফিস_আইডি'])। যোগফল ()। রূপান্তর (ল্যাম্বদা এক্স: x / np.sum (x) * 100) অতএব, আমি এটিকে ঠিক করার জন্য একটি পৃথক উত্তর পোস্ট করব।
মাইটি কুরিসিয়াস

1

আমি যে সহজ উপায়টি ব্যবহার করেছি তা হ'ল 2 গ্রুপবিয়ের পরে সাধারণ বিভাগ করার পরে একত্রীকরণ।

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

এটি প্রতি অফিস অনুপাতের একটি সিরিজ প্রদান করে - এটি নিজস্ব ব্যবহার করা যেতে পারে বা মূল ডেটাফ্রেমে নির্ধারিত হতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.