Skip to main content
 首页 » 编程设计

python之根据多列中的值创建新的数据框列

2025年05月04日12pengyingh

仅供引用,性能/速度对于这个问题不很重要。

我有一个名为 cost_table 的现有 pandas 数据框 ...

+----------+---------+------+-------------------------+-----------------+ 
| material | percent | qty  | price_control_indicator | acct_assign_cat | 
+----------+---------+------+-------------------------+-----------------+ 
| abc111   | 1.00    |   50 | v                       | #               | 
| abc222   | 0.25    | 2000 | s                       | #               | 
| xyz789   | 0.45    |    0 | v                       | m               | 
| def456   | 0.9     |    0 | v                       | #               | 
| 123xyz   | 0.2     |    0 | v                       | m               | 
| lmo888   | 0.6     |    0 | v                       | m               | 
+----------+---------+------+-------------------------+-----------------+ 

我需要根据多个字段中的值添加一个字段cost_source。

Google 上出现的大多数答案都涉及列表理解或三元运算符,但这些答案仅包含基于一列中的值的逻辑。例如,

cost_table['cost_source'] = ['map' if qty > 0 else None for qty in cost_table['qty']]

这基于一列中的值工作,但我不知道如何扩展它以包含多列中的逻辑(或者它是否可能?)。它似乎也不是一个非常可读/可维护的解决方案。

我尝试将 for in 循环与 if elif 语句一起使用,但 cost_table['cost_source'] 中的值保持不变并且是None 所有行。但是,如果我在循环中打印每一行,则 row['cost_source'] 具有所需的值。

d = { 
  'material': ['abc111', 'abc222', 'xyz789', 'def456', '123xyz', 'lmo888'], 
  'percent': [1, .25, .45, .9, .2, .6], 
  'qty': [50, 2000, 0, 0, 0, 0], 
  'price_control_indicator': ['v', 's','v', 'v', 'v', 'v'], 
  'acct_assign_cat': ['#', '#', 'm', '#', 'm', 'm'] 
} 
 
cost_table = pd.DataFrame(data=d) 
 
cost_table['cost_source'] = None 
 
for index, row in cost_table.iterrows(): 
  if (row['qty'] > 0) or (row['price_control_indicator'] == "s") or (row['acct_assign_cat'] == "#"): 
    row['cost_source'] = "map" 
  elif (row['percent'] >= 40) and (row['acct_assign_cat'] == "m"): 
    row['cost_source'] = "vendor" 
  else: 
    row['cost_source'] = None 
 
  print(row['cost_source']) # outputs map, vendor, or None as expected 
 
print(cost_table) 

哪个输出...

+----------+---------+------+-------------------------+-----------------+-------------+ 
| material | percent | qty  | price_control_indicator | acct_assign_cat | cost_source | 
+----------+---------+------+-------------------------+-----------------+-------------+ 
| abc111   | 1.00    |   50 | v                       | #               | None        | 
| abc222   | 0.25    | 2000 | s                       | #               | None        | 
| xyz789   | 0.45    |    0 | v                       | m               | None        | 
| def456   | 0.9     |    0 | v                       | #               | None        | 
| 123xyz   | 0.2     |    0 | v                       | m               | None        | 
| lmo888   | 0.6     |    0 | v                       | m               | None        | 
+----------+---------+------+-------------------------+-----------------+-------------+ 

这是我想要的结果......

+----------+---------+------+-------------------------+-----------------+-------------+ 
| material | percent | qty  | price_control_indicator | acct_assign_cat | cost_source | 
+----------+---------+------+-------------------------+-----------------+-------------+ 
| abc111   | 1.00    |   50 | v                       | #               | map         | 
| abc222   | 0.25    | 2000 | s                       | #               | map         | 
| xyz789   | 0.45    |    0 | v                       | m               | vendor      | 
| def456   | 0.9     |    0 | v                       | #               | map         | 
| 123xyz   | 0.2     |    0 | v                       | m               | None        | 
| lmo888   | 0.6     |    0 | v                       | m               | vendor      | 
+----------+---------+------+-------------------------+-----------------+-------------+ 

请您参考如下方法:

如@bazinga 所述,使用 df.apply(lambda x: fun(x),但参数 axis=1,因此 lambda 函数应用于行按行(默认为逐列)。

d = { 
  'material': ['abc111', 'abc222', 'xyz789', 'def456', '123xyz', 'lmo888'], 
  'percent': [100, 25, 45, 90, 20, 60], 
  'qty': [50, 2000, 0, 0, 0, 0], 
  'price_control_indicator': ['v', 's','v', 'v', 'v', 'v'], 
  'acct_assign_cat': ['#', '#', 'm', '#', 'm', 'm'] 
} 
 
cost_table = pd.DataFrame(data=d) 
 
def process_row(row): 
    if (row['qty'] > 0) or (row['price_control_indicator'] == "s") or (row['acct_assign_cat'] == "#"): 
        return "map" 
    elif (row['percent'] >= 40) and (row['acct_assign_cat'] == "m"): 
        return "vendor" 
    else: 
        return None 
 
cost_table['cost_source'] = cost_table.apply(lambda row: process_row(row), axis=1) 
 
print(cost_table) 

(我还纠正了一个不一致的地方:在数据中 procents 应该大概乘以 100)