Итерация по фрейму данных и обновление на основе условий словаря

#python #pandas #xlsx

#python #pandas #xlsx

Вопрос:

У меня есть следующий файл xlsx, над которым мне нужно работать:

Я хочу выполнить итерацию по фрейму данных, и если код элемента столбца содержит ключ словаря, я хочу проверить в той же строке, содержит ли значение словаря [0] (первая позиция в кортеже), и если содержит, я хочу вставить значение словаря 1 (вторая позиция в кортеже) в другую строку.столбец с именем SKU

Фрейм данных: #df3 = df2.append(df1) введите описание изображения здесь

 catp = {"2755":(('24','002'),('25','003'),('26','003'),('27','004'),('28','005'),('29','006'),('30','007'),('31','008'),
                ('32','009'),('32','010'),('33','011'),('34','012'),('35','013'),('36','014')),
        "2513":(('38','002'),('40','003'),('42','004'),('44','005'),('46','006'),('48','007'),('50','008'),('52','009'),
               ('54','010'))}

for i, row in df3.iterrows():
    if catp.key() in df3['ITEM CODE'][i] and catp.value()[0] in df3['TG'][i]:
            codmarime = catp.value()[1]
            df3['SKU'][i] = '20' df3['ITEM CODE'][i] [i] codmarime

    else:
        df3['SKU'][i] = '20' df3['ITEM CODE'][i] '???'
  

Если найдено 2755 и 24 артикула = ‘202755638002’

Если найдено 2513 и 44 SKU = ‘202513123005’

Вывод xlsx введите описание изображения здесь

Комментарии:

1. Также предоставьте образец фрейма данных

2. Это нормально? imgur.com/enrKxa6 , вставленный также в сообщение

3. Вы предоставили картинку . Пожалуйста, предоставьте текстовое содержимое.

4. Ваш код содержит codmarime = '' в конце оба варианта if и else . Какова цель этих замен?

5. Отредактировано и удалено codmarime = ‘ ‘ . В какой-то момент это было для тестирования.

Ответ №1:

Поскольку вы не смогли предоставить текстовые данные для создания хотя бы фрагмента вашего фрейма данных, я скопировал из вашего изображения 3 строки, создав свой тестовый фрейм данных:

 df3 = pd.DataFrame(data=[
    [ '1513452', 'AVRO D2', '685', 'BLACK/BLACK/ANTRACITE', '24', 929.95, '8052644627565' ],
    [ '2513452', 'AVRO D2', '685', 'BLACK/BLACK/ANTRACITE', '21', 929.95, '8052644627565' ],
    [ '2755126', 'AMELIA',  'Y17', 'DARK-DENIM',            '24', 179.95, '8052644627565' ]],
    columns=[ 'ITEM CODE', 'ITEM', 'COLOR', 'COLOR CODE', 'TG', 'PRICE', 'EAN' ])
  

Подробные сведения:

  • Первая строка не содержит ни одного из catp ключей в ITEM CODE столбце.
  • Вторая строка: ITEM CODE содержит один из ваших кодов (2513), но для TG столбца ни один кортеж, сохраненный под 2513 ключом, не содержит первого элемента == 21.
  • Третья строка: ITEM CODE содержит один из ваших кодов (2755), TG == 24, а среди сохраненных кортежей 2755 есть один == 24.

Затем мы должны определить пару вспомогательных функций:

 def findContainedCodeAndVal(dct, str):
    for eachKey in dct.keys():
        if str.find(eachKey) >= 0:
            return (eachKey, dct[eachKey])
    else:
        return (None, None)
  

Эта функция пытается найти в dct ключе, содержащемся в str .
Он возвращает 2-кортеж, содержащий найденный ключ и связанное с ним значение dct .

 def find2ndElem(tuples, str):
    for tpl in tuples:
        if tpl[0] == str:
            return tpl[1]
    else:
        return ''
  

Эта функция проверяет каждый кортеж, начиная с tuples его первого элемента.
== str и возвращает второй элемент из этого кортежа.

И последняя определяемая функция — это функция, которая будет применяться к каждой строке из вашего фрейма данных. Он возвращает значение, которое будет сохранено в SKU столбце:

 def fn(row):
    ind = row.name  # Read row index
    iCode = row['ITEM CODE']
    k, val = findContainedCodeAndVal(catp, iCode)
    codmarime = ''
    if k:
        tg = row.TG
        codmarime = find2ndElem(val, tg)
    if codmarime == '':
        codmarime = '???'
    return f'20/{iCode}/{ind}/{codmarime}'
  

Обратите внимание, что он использует ваш catp словарь.

В демонстрационных целях я ввел в возвращаемое значение дополнительные косые черты, разделяющие смежные части. В целевой версии удалите их.

И последнее, что нужно сделать, это вычислить SKU столбец вашего фрейма данных, применяя fn функцию к каждой строке df3 и сохраняя результат в SKU столбце:

 df3['SKU'] = df3.apply(fn, axis=1)
  

Когда вы печатаете фрейм данных (содержащий мои тестовые данные), SKU столбец будет
содержать:

 20/1513452/0/???
20/2513452/1/???
20/2755126/2/002
  

Комментарии:

1. Здравствуйте, у меня проблема с вашим кодом, когда ячейки пусты: —-> 4 df3[‘SKU’] = df3.apply(fn, axis = 1) Ошибка атрибута: («объект’float’ не имеет атрибута ‘find'», ‘произошел с индексом 0’)

2. Похоже, что ошибка возникает при if str.find(eachKey)>= 0: потому что str — это либо NaN , либо None (проверьте, в каком случае это так). Чтобы избежать этой ошибки, перед каждым ключом в dct.keys(): вы должны проверить str . Если он пуст ( NaN или None ), то функция должна вернуть (None, None) . Другим решением является замена всех значений None / NaN пустой строкой ( fillna() ). Если было предоставлено какое-то значение, остальная часть этой функции должна быть выполнена. Другое решение — заменить значения None пустой строкой ( fillna() ).

Ответ №2:

Я не могу правильно понять вопрос, а просто исправляю ошибки, которые я вижу в вашем коде:

if catp.key() in df3['ITEM CODE'][i] and catp.value()[0] in df3['TG'][i]:

Это неверно.

Я использую другой подход, который должен работать, если я понимаю конечную цель

 for key in catp.keys():
     xdf = df3.loc[(df3['SKU'].astype(str).contains(key)) amp; (df3['SKU'].astype(str).contains(catp[key][0])]
     if len(xdf)>0:
         for i, row in xdf.iterrows():
                codmarime = catp[key][1]
                df3.at[i,'SKU'] = '20' row['ITEM CODE'][i] [i] codmarime