вычисление нового столбца в Pandas, используя значения словаря и ключи - PullRequest
2 голосов
/ 02 октября 2019

У меня есть фрейм данных, который содержит список заказов 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 ]

1 голос
/ 02 октября 2019

Мне нравится твой вопрос, поэтому я взял перерыв на обед, чтобы попробовать. Я предполагаю, что вы можете выбрать формат набора данных. Я предлагаю вам сохранить их в виде списков. Вот мой собственный набор данных, основанный на вашем.

 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]. Например: [(«Кофе», 2), («Салат», 2), («Курица», 1), («Стейк», 1)]. Он принадлежит подсписку с именем order, тогда к 1-му элементу обращаются по порядку [d] [0], а к 2-му - по ссылочному порядку [d] [1]. Итак, заказ [0] [0] - это кофе, заказ [1] [0] - салат, заказ [0] [1] - 2, а заказ [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    
1 голос
/ 02 октября 2019

Вы можете использовать .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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...