使用字典值和键在熊猫中计算新列

时间:2019-10-02 08:49:53

标签: python pandas list dictionary

我有一个数据框,其中包含订单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)

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

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分:1)

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

 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]]

这是一个非常简单的代码,它基于格式[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