Я пытаюсь создать новый столбец, содержащий все ассортименты (Asst 1–50), которым может принадлежать SKU. Артикул относится к ассортименту, если он отмечен знаком «х» в соответствующем столбце.
Сценарий должен иметь возможность перебирать строки в столбце SKU и проверять наличие «x» в любом из столбцов ASST. Если он найдет его, скопируйте имя этого столбца ассортимента во вновь созданный столбец «все ассортименты».
После одного лайнера:
Я пытался это сделать, используя метод df.apply, но, похоже, я не могу понять это правильно.
def assortment_crunch(row):
if row == 'x':
df['Asst #1'].apply(assortment_crunch):
моя попытка на самом деле не учитывает необходимость перебирать все столбцы «asst» и то, как назначить этот столбец вновь созданному.
да! всегда будет максимум 50. Иногда все не будет заполнено, но лист всегда будет расширяться до 50.
Я не уверен, что это самый эффективный способ, но вы можете попробовать это.
Вместо того, чтобы apply
обращаться к столбцу, apply
ко всему DF, чтобы получить доступ к строке. Затем вы можете перебрать каждый столбец и создать значение для последнего столбца:
def make_all_assortments_cell(row):
assortments_in_row = []
for i in range(1, 51):
column_name = f'Asst #{i}'
if (row[column_name] == 'x').any():
assortments_in_row.append(row[column_name])
return ", ".join(assortments_in_row)
df["All Assortments"] = df.apply(make_all_assortments_cell)
Я считать, это будет работать, хотя я не проверял.
@richardec спасибо за редактирование! Каков эффект .any
здесь?
Потому что когда вы запускаете что-то вроде row[column_name] == 'x'
, вы не получаете значения True/False, как можно было бы ожидать. Вместо этого вы получаете «маску», которая представляет собой объект Series той же длины, что и row[column_name]
, где каждое значение равно True, если оно x
, и False в противном случае. .any()
возвращает True, если в маске есть еще одно значение True, False, если их нет. :)
Вот супер быстрый («векторизованный») однострочник:
asst_cols = df.filter(like='Asst #')
df['All Assortment'] = [', '.join(asst_cols.columns[mask]) for mask in asst_cols.eq('x').to_numpy()]
Объяснение:
df.filter(like='Asst #')
— возвращает все столбцы, в названии которых есть Asst #
.eq('x')
- точно так же, как == 'x'
, просто проще связывать такие функции из-за беспорядка в скобках, который мог бы возникнуть в противном случаеto_numpy()
- преобразует фрейм данных маски в список масок
Вы заранее знаете, сколько столбцов Asst# будет?