#python #pandas #merge #pandas-groupby
#python #pandas #слияние #pandas-groupby
Вопрос:
У меня есть данные, которые я сгруппировал по двум столбцам и подвел промежуточный итог. Я использовал .loc для разделения дочерней группы и pd.merge для добавления каждой в виде столбца с итогами для родительской группы. Это не было безумным количеством ввода, поскольку дочерних групп было не так много, но я надеюсь найти более эффективный способ для будущих проектов. Мой код довольно простой, и у меня есть привычка делать все долго, но мне кажется, что для больших наборов данных должен быть более простой способ.
import pandas as pd
data = {"Company":["a","b","c","b","a","c","a","a","b"], "Product":[3,2,2,1,4,4,3,2,1], "Qty":[2,4,8,1,8,3,6,4,5]}
#Create df and group by first two columns
df = pd.DataFrame(data)
grouped_prod_df=df.groupby(["Company","Product"])
qty_sum= grouped_prod_df.sum()
qty_sum_df =pd.DataFrame(qty_sum.reset_index())
# find total qtys of each product
product_1 = qty_sum_df.loc[qty_sum_df["Product"] == 1]
product_2 = qty_sum_df.loc[qty_sum_df["Product"] == 2]
product_3 = qty_sum_df.loc[qty_sum_df["Product"] == 3]
product_4 = qty_sum_df.loc[qty_sum_df["Product"] == 4]
product_1_df = pd.DataFrame(product_1)
product_1_df = product_1_df[["Company","Qty"]]
product_1_df = product_1_df.rename(columns={"Qty":"Product_1"})
product_2_df= pd.DataFrame(product_2)
product_2_df = product_2_df[["Company","Qty"]]
product_2_df = product_2_df.rename(columns={"Qty":"Product_2"})
product_3_df= pd.DataFrame(product_3)
product_3_df = product_3_df[["Company","Qty"]]
product_3_df = product_3_df.rename(columns={"Qty":"Product_3"})
product_4_df= pd.DataFrame(product_4)
product_4_df = product_4_df[["Company","Qty"]]
product_4_df = product_4_df.rename(columns={"Qty":"Product_4"})
#sum company grand totals
company_df = df[["Company","Qty"]]
grouped_company_df=company_df.groupby(["Company"])
company_sum= grouped_company_df.sum()
company_sum_df = pd.DataFrame(company_sum)
#merge product totals in column next to grand total with product as column header and repeat for
#other columns
all_prod = pd.merge(company_sum_df, product_1_df, on="Company", how="left")
all_prod = pd.merge(all_prod, product_2_df, on="Company", how="left")
all_prod = pd.merge(all_prod, product_3_df, on="Company", how="left")
all_prod = pd.merge(all_prod, product_4_df, on="Company", how="left")
all_prod
РЕДАКТИРОВАТЬ: пытался сделать свой код более общим и в итоге не работал, но я исправил и протестировал его сейчас. Вывод должен быть следующим с количеством, показывающим общее количество всех продуктов по компаниям.
Company Qty Product_1 Product_2 Product_3 Product_4
0 a 20 NaN 4 8.0 8.0
1 b 10 6.0 4 NaN NaN
2 c 11 NaN 8 NaN 3.0
Любая помощь приветствуется.
Комментарии:
1. ваш общий код требует исправлений (возвращает ряд ошибок). Пожалуйста, опубликуйте ожидаемый результат, и мы сможем работать оттуда.
2. Здорово, что вы поделились своим кодом и генерацией данных. Но не могли бы вы уточнить, что именно вы хотите на простом английском языке? а не просто код? Таким образом, вам будет легче помочь.
3. Я ищу более эффективный способ сделать это, когда мне не нужно указывать каждый продукт, чтобы получить итоговые данные по продуктам в столбцах и общее количество, суммирующее все продукты.
Ответ №1:
На самом простом уровне вам нужно только сделать:
(
df.groupby(["Company","Product"])
.sum()
.unstack(level='Product')['Qty']
.assign(Qty=lambda df: df.sum(axis='columns'))
)
И это даст вам:
Product 1 2 3 4 Qty
Company
a NaN 4.0 8.0 8.0 20.0
b 6.0 4.0 NaN NaN 10.0
c NaN 8.0 NaN 3.0 11.0
Если имена столбцов действительно должны совпадать, вы можете переименовать их:
(
df.groupby(["Company","Product"])
.sum()
.unstack(level='Product')['Qty']
.rename(columns=lambda c: f"Product_{c}")
.assign(Qty=lambda df: df.sum(axis='columns'))
.rename_axis(None, axis='columns')
)
И это дает вам:
Product_1 Product_2 Product_3 Product_4 Qty
Company
a NaN 4.0 8.0 8.0 20.0
b 6.0 4.0 NaN NaN 10.0
c NaN 8.0 NaN 3.0 11.0
Комментарии:
1. Спасибо! Это было именно то, что я искал.