【问题标题】:calculating a new column in Pandas using dictionary values and keys使用字典值和键计算 Pandas 中的新列
【发布时间】:2020-01-31 12:54:13
【问题描述】:

我有一个包含订单列表order_items 及其总价order_price 的数据框。 order_type 列包含订单类型:早餐、午餐或晚餐。

我的目标是确认给定的总数 order_price 是正确的。通过将数量(元组中的第二个项目)乘以项目价格。然后将一个订单的所有价格相加并将其存储在一个新列中order_price_checked

我的数据集示例:

    order_id    order_items                                                     order_type  order_price
0   ORDB10489   [('Coffee', 4), ('Salad', 10), ('Chicken', 8), ('Steak', 10)]   Lunch       1002.00
1   ORDZ00319   [('Fish&Chips', 9), ('Pasta', 5), ('Shrimp', 3)]                Dinner      614.50
2   ORDB00980   [('Pasta', 6), ('Fish&Chips', 10)]                              Dinner      515.00
3   ORDY10003   [('Chicken', 7), ('Steak', 1)]                                  Lunch       269.00
4   ORDK04121   [('Steak', 9), ('Chicken', 5)]                                  Lunch       565.00
5   ORDC10404   [('Burger', 3), ('Salad', 6), ('Fries', 7)]                     Lunch       280.20
6   ORDK05183   [('Chicken', 1), ('Steak', 10), ('Fries', 4), ('Salad', 6)]     Lunch       633.20

我已将每个 order_type 的价格存储在单独的字典中。 例如,lunchDict 用于午餐订单。

{'Burger': 31.0, 'Fries': 12.0, 'Chicken': 32.0, 'Salad': 17.2, 'Steak': 45.0}

我的方法是将元组中的第一项与字典键匹配。如果它与键匹配,那么我将元组中的第二项(数量)乘以相应键的值(价格)。 然后获取所有订单的总和并将其添加到新列order_price_checked

期望的输出(我只显示两列以节省空间): 例如索引 1 和 4 显示我们的价格错误。

     order_price   order_price_checked
   0    1002.00     1002.00
   1    614.50      600.20
   2    515.00      515.00
   3    269.00      269.00
   4    565.00      500.00
   5    280.20      280.20
   6    633.20      633.20

我尝试在for loop 中做到这一点:

for item in dirtyData['order_items']:
    for mytuple in item:
        if mytuple[0] in breakfastDict:
            tot=mytuple[1]*breakfastDict[mytuple[0]]
print(tot)

但这不是一个明确的方法,我不知道我正在处理哪一行。 任何输入都会有所帮助。谢谢

【问题讨论】:

  • 如果您提供午餐或晚餐的价格dict 可能会更好,因为您的样品不含早餐:P
  • 哦,是的!好吧..

标签: python pandas list dictionary


【解决方案1】:

您可以在每一行上使用 .apply 并使用自定义函数进行求和。

示例数据集(不能pd.read_clipboard你的,因为它有空格;这就是为什么最好给出一个带有代码的示例来创建日期集) 将熊猫导入为 pd

df = pd.DataFrame(columns = ['order_id','order_items','order_type', 'order_price'],
                  data=[
                      ('ORDB10489', [('Coffee', 4), ('Salad', 10), ('Chicken', 8), ('Steak', 10)], 'Lunch', 1002.00),
                      ('ORDZ00319', [('Fish&Chips', 9), ('Pasta', 5), ('Shrimp', 3)], 'Dinner', 614.50)
                 ])

设置价格字典,以及在膳食类型及其各自定价字典之间映射的字典:

dinner_dict = {'Shrimp': 100, 'Pasta': 60, 'Fish&Chips': 14.5/9}
lunch_dict = {'Coffee': 33, 'Salad': 33, 'Chicken': 33, 'Steak': 10000}

meal_dict = {'Dinner': dinner_dict, 'Lunch': lunch_dict}

定义自定义函数(您也可以使用内联 lambda 来实现,但这样更清晰):

def sum_items_in_order(order, meal_dict):
    return sum(item[1]*meal_dict[order['order_type']][item[0]] for item in order['order_items'])

您的结果将符合要求:

df.apply(lambda order: sum_items_in_order(order, meal_dict), axis=1)

【讨论】:

  • pd.read_clipboard 的好点子。我会记住这一点。再次感谢。
【解决方案2】:

我喜欢你的问题,所以我利用午休时间来试一试。 我假设你可以选择你的数据集格式。我建议您将它们保留为列表。 这是我自己基于你的数据集。

 orders = [['ORDB10489',[('Coffee', 2), ('Salad', 2), ('Chicken', 1), ('Steak',    1)],'Lunch',40],
           ['ORDZ00319',[('Fish&Chips', 1), ('Pasta', 3), ('Shrimp', 2)],'Dinner',57.5],
           ['ORDB00980',[('Pasta', 4), ('Fish&Chips', 3)],'Dinner',50.5],
           ['ORDC10404',[('Burger', 1), ('Salad', 1), ('Coffee', 1)],'Lunch',18]]

带有价格的菜单:

 lunch = [['Coffee',2.00],['Salad',6.50],['Burger',8.00],['Chicken',10.00],['Steak',13.00]]
 dinner = [['Fish&Chips',7.50],['Pasta',7.00],['Shrimp',14.50]]

这是一个非常简单的代码,基于 item[i][j] 格式的变量访问。例如:[('Coffee', 2), ('Salad', 2), ('Chicken', 1), ('Steak', 1)]。它属于一个名为 order 的子列表,然后通过 order[d][0] 访问第一个元素,通过引用 order[d][1] 访问第二个元素。所以,order[0][0] 是咖啡,order[1][0] 是沙拉,order[0][1] 是 2,order[2][1] 是 1。

代码:

# reading all the orders, one by one    
for o in range(len(orders)):    
   order_id       = orders[o][0] 
   order          = orders[o][1]
   paid           = []  # empty list for every new order

   # reading all dishes, one by one 
   for d in range(len(order)): 
      dish      = order[d][0] 
      quantity  = order[d][1]
      service = orders[o][2] 

      if service == 'Lunch':
         for lu in range(len(lunch)):
             if dish == lunch[lu][0]:
                amount = quantity*(lunch[lu][1]) 
                paid.append(amount)
      else :
         for di in range(len(dinner)):
            if dish == dinner[di][0]:
                amount = quantity*(dinner[di][1])
                paid.append(amount) # adding to the paying list

due     = sum(paid) #sum of dishes in the list
bill    = orders[o][3]
print(order_id,due,bill)

输出:

ORDB10489 40.0 40
ORDZ00319 57.5 57.5
ORDB00980 50.5 50.5
ORDC10404 16.5 18    

【讨论】:

  • 多么干净的解决方案。谢谢!
猜你喜欢
  • 2020-09-19
  • 1970-01-01
  • 2021-03-15
  • 1970-01-01
  • 2019-02-08
  • 2017-06-06
  • 1970-01-01
  • 2017-02-03
  • 2018-03-08
相关资源
最近更新 更多