python - Pandas:将函数应用于每个组并将结果存储在新列中

标签 python pandas function group-by apply

我有一个项目数据框,例如:

item_df = pd.DataFrame({'BarCode': ['12345678AAAA', '12345678BBBB', '12345678CCCC',
                                    '12345678ABCD', '12345678EFGH', '12345678IJKL',
                                    '67890123XXXX', '67890123YYYY', '67890123ZZZZ',
                                    '67890123ABCD', '67890123EFGH', '67890123IJKL'],
                        'Extracted_Code': ['12345678','12345678', '12345678','12345678','12345678','12345678',
                                           '67890123','67890123', '67890123','67890123', '67890123','67890123'],
                        'Description': ['Fruits', 'Fruits', 'Fruits', 'Apples', 'Oranges', 'Mangoes',
                                        'Snacks', 'Snacks', 'Snacks', 'Yoghurt', 'Cookies', 'Oats'],
                        'Category': ['H', 'H', 'H', 'M', 'T', 'S', 'H', 'H', 'H', 'M', 'M', 'F'],
                        'Code': ['0', '2', '3', '1', '2', '4', '0', '2', '3', '3', '4', '2'],
                        'Quantity': [99, 77, 10, 52, 11, 90, 99, 77, 10, 52, 11, 90],
                        'Price': [12.0, 10.5, 11.0, 15.6, 12.9, 67.0, 12.0, 10.5, 11.0, 15.6, 12.9, 67.0]})

item_df = item_df.sort_values(by=['Extracted_Code', 'Category', 'Code'])
item_df['Combined'] = np.NaN

我想要实现的目标有点棘手。我必须对 ['Extracted_Code'] 执行 groupby,并为每个组创建一个新列 CombinedCombined 列的值基于:

  1. 对于 Category='H' 的行,Combined 将具有 NaN 值。
  2. 对于类别不是“H”的行,假设如果我们采用类别=“M”的行,那么该特定行的组合列将具有相同类别中类别=“H”的行 json 列表组,并且其代码小于或等于该特定行的代码。

我想要的结果是:

  BarCode        Extracted_Code   Description   Category   Code    Quantity   Price    Combined
0 12345678AAAA   12345678         Fruits        H          0       99         12.0     NaN
1 12345678BBBB   12345678         Fruits        H          2       77         10.5     NaN
2 12345678CCCC   12345678         Fruits        H          3       10         11.0     NaN
3 12345678ABCD   12345678         Apples        M          1       52         15.6     [{'BarCode': '12345678AAAA', 'Description': 'Fruits', 'Category': 'H', 'Code': '0', 'Quantity': 99, 'Price': 12.0}]
4 12345678IJKL   12345678         Mangoes       S          4       90         67.0     [{'BarCode': '12345678AAAA', 'Description': 'Fruits', 'Category': 'H', 'Code': '0', 'Quantity': 99, 'Price': 12.0},
                                                                                        {'BarCode': '12345678BBBB', 'Description': 'Fruits', 'Category': 'H', 'Code': '2', 'Quantity': 77, 'Price': 10.5},
                                                                                        {'BarCode': '12345678CCCC', 'Description': 'Fruits', 'Category': 'H', 'Code': '3', 'Quantity': 10, 'Price': 11.0}]
5 12345678EFGH   12345678         Oranges       T          2       11         12.9     [{'BarCode': '12345678AAAA', 'Description': 'Fruits', 'Category': 'H', 'Code': '0', 'Quantity': 99, 'Price': 12.0},
                                                                                        {'BarCode': '12345678BBBB', 'Description': 'Fruits', 'Category': 'H', 'Code': '2', 'Quantity': 77, 'Price': 10.5}]
6 67890123IJKL   67890123         Oats          F          2       90         67.0     [{'BarCode': '67890123XXXX', 'Description': 'Snacks', 'Category': 'H', 'Code': '0', 'Quantity': 99, 'Price': 12.0},
                                                                                        {'BarCode': '67890123YYYY', 'Description': 'Snacks', 'Category': 'H', 'Code': '2', 'Quantity': 77, 'Price': 10.5}]
7 67890123XXXX   67890123         Snacks        H          0       99         12.0     NaN
8 67890123YYYY   67890123         Snacks        H          2       77         10.5     NaN
9 67890123ZZZZ   67890123         Snacks        H          3       10         11.0     NaN
10 67890123ABCD  67890123         Yoghurt       M          3       52         15.6     [{'BarCode': '67890123XXXX', 'Description': 'Snacks', 'Category': 'H', 'Code': '0', 'Quantity': 99, 'Price': 12.0},
                                                                                        {'BarCode': '67890123YYYY', 'Description': 'Snacks', 'Category': 'H', 'Code': '2', 'Quantity': 77, 'Price': 10.5},
                                                                                        {'BarCode': '67890123ZZZZ', 'Description': 'Snacks', 'Category': 'H', 'Code': '3', 'Quantity': 10, 'Price': 11.0}]
11 67890123EFGH  67890123         Cookies       M          4       11         12.9     [{'BarCode': '67890123XXXX', 'Description': 'Snacks', 'Category': 'H', 'Code': '0', 'Quantity': 99, 'Price': 12.0},
                                                                                        {'BarCode': '67890123YYYY', 'Description': 'Snacks', 'Category': 'H', 'Code': '2', 'Quantity': 77, 'Price': 10.5},
                                                                                        {'BarCode': '67890123ZZZZ', 'Description': 'Snacks', 'Category': 'H', 'Code': '3', 'Quantity': 10, 'Price': 11.0}]

这就是我为获取行 json 列表所做的操作:

item_df.groupby(['Extracted_Code', 'Category', 'Code']).apply(lambda x: x.to_dict('records')).reset_index(name='Combined')

但我对如何将条件应用于每个组而不丢失最终结果中的任何列感到困惑。

最佳答案

您可以执行自合并,并过滤掉符合您条件的行:

m = df.reset_index().merge(df, on="Extracted_Code", suffixes=("_x", ""))
m = m[ (m["Category"] == "H") & (m["Code"] <= m["Code_x"]) & (m["Category_x"] != "H") ] 
    index     BarCode_x Extracted_Code Description_x Category_x Code_x  Quantity_x  Price_x       BarCode Description Category Code  Quantity  Price
18      3  12345678ABCD       12345678        Apples          M      1          52     15.6  12345678AAAA      Fruits        H    0        99   12.0
24      5  12345678IJKL       12345678       Mangoes          S      4          90     67.0  12345678AAAA      Fruits        H    0        99   12.0
25      5  12345678IJKL       12345678       Mangoes          S      4          90     67.0  12345678BBBB      Fruits        H    2        77   10.5
26      5  12345678IJKL       12345678       Mangoes          S      4          90     67.0  12345678CCCC      Fruits        H    3        10   11.0
30      4  12345678EFGH       12345678       Oranges          T      2          11     12.9  12345678AAAA      Fruits        H    0        99   12.0
31      4  12345678EFGH       12345678       Oranges          T      2          11     12.9  12345678BBBB      Fruits        H    2        77   10.5
37     11  67890123IJKL       67890123          Oats          F      2          90     67.0  67890123XXXX      Snacks        H    0        99   12.0
38     11  67890123IJKL       67890123          Oats          F      2          90     67.0  67890123YYYY      Snacks        H    2        77   10.5
61      9  67890123ABCD       67890123       Yoghurt          M      3          52     15.6  67890123XXXX      Snacks        H    0        99   12.0
62      9  67890123ABCD       67890123       Yoghurt          M      3          52     15.6  67890123YYYY      Snacks        H    2        77   10.5
63      9  67890123ABCD       67890123       Yoghurt          M      3          52     15.6  67890123ZZZZ      Snacks        H    3        10   11.0
67     10  67890123EFGH       67890123       Cookies          M      4          11     12.9  67890123XXXX      Snacks        H    0        99   12.0
68     10  67890123EFGH       67890123       Cookies          M      4          11     12.9  67890123YYYY      Snacks        H    2        77   10.5
69     10  67890123EFGH       67890123       Cookies          M      4          11     12.9  67890123ZZZZ      Snacks        H    3        10   11.0

.reset_index() 允许您然后 .groupby("index") 然后您可以添加您的 .to_dict("records") 至:

combined = m.groupby("index").apply(lambda group: 
   group[["BarCode", "Description", "Category", 
          "Code", "Quantity", "Price"
   ]].to_dict("records")
).rename("Combined")

然后您可以.join:

>>> df.join(combined)
         BarCode Extracted_Code Description Category Code  Quantity  Price                                           Combined
0   12345678AAAA       12345678      Fruits        H    0        99   12.0                                                NaN
1   12345678BBBB       12345678      Fruits        H    2        77   10.5                                                NaN
2   12345678CCCC       12345678      Fruits        H    3        10   11.0                                                NaN
3   12345678ABCD       12345678      Apples        M    1        52   15.6  [{'BarCode': '12345678AAAA', 'Description': 'F...
5   12345678IJKL       12345678     Mangoes        S    4        90   67.0  [{'BarCode': '12345678AAAA', 'Description': 'F...
4   12345678EFGH       12345678     Oranges        T    2        11   12.9  [{'BarCode': '12345678AAAA', 'Description': 'F...
11  67890123IJKL       67890123        Oats        F    2        90   67.0  [{'BarCode': '67890123XXXX', 'Description': 'S...
6   67890123XXXX       67890123      Snacks        H    0        99   12.0                                                NaN
7   67890123YYYY       67890123      Snacks        H    2        77   10.5                                                NaN
8   67890123ZZZZ       67890123      Snacks        H    3        10   11.0                                                NaN
9   67890123ABCD       67890123     Yoghurt        M    3        52   15.6  [{'BarCode': '67890123XXXX', 'Description': 'S...
10  67890123EFGH       67890123     Cookies        M    4        11   12.9  [{'BarCode': '67890123XXXX', 'Description': 'S...

关于python - Pandas:将函数应用于每个组并将结果存储在新列中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76334272/

相关文章:

python - 按星期几排序列?

python - 用于转换的正则表达式(不使用多个语句)

c++ - 从函数返回对象

python - 在 python 中,对逗号分隔的域名列表执行 DNS 查询的最有效方法是什么?

python - 将数据库数据从 DEV 移动到 PRODUCTION,最佳实践?

python - 根据行条件分配组号 [Python]

javascript - 'this.randomGenes' 为什么不是一个函数?

python - 如何在netbeans中运行python?

python - 如果命令行程序不确定 stdout 的编码,它应该输出什么编码?

c - 使用递归函数添加数字