#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’
Комментарии:
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