Фильтровать DataFrame для большинства совпадений

У меня есть список (list_to_match = ['a','b','c','d']) и фрейм данных, как показано ниже:

Индекс Один Два Три Четыре 1 а б д с 2 б б д д 3 а б д 4 с б с д 5 а б с г 6 а б с 7 а с с ф 8 а ф с 9 а б 10 а б т д 11 а б г ... ... ... ... ... 100 а б с д

Моя цель состояла бы в том, чтобы отфильтровать строки с наибольшим количеством совпадений со списком в соответствующей позиции (например, позиция 1 в списке должна соответствовать столбцу 1, позиция 2 столбцу 2 и т. д.). В этом конкретном случае, исключая строку 100, строки 5 и 6 будут выбраны, поскольку они соответствуют «a», «b» и «c», но если строка 100 должна быть включена, строка 100 и все остальные строки, соответствующие всем элементам был бы избранным. Также список может измениться по длине, например. list_to_match = ['a','b'].

Спасибо за вашу помощь!

Так вам нужны строки фильтра, количество совпадений которых равно максимальному количеству совпадений среди всех строк?

ansev 10.01.2023 18:46

Я подумал, может быть, цикл, в котором он сначала фильтрует фрейм данных для первого столбца, если он равен «a», а затем, если длина результирующего нарезанного фрейма данных отличается от «0», он переходит к следующему и пытается фильтровать ( уже отфильтровано с помощью «a») кадра данных с помощью «b», и если длина этой новой отфильтрованной базы данных выше «0», она идет дальше и т. д., и цикл прерывается всякий раз, когда длина отфильтрованного кадра данных равна нулю, выбирая предыдущий уровень как хороший

Dario Bani 10.01.2023 19:13

Я думаю, что в этом случае вам нужно только решение с cummin или cumprod, такое как решение mozway или мое обновленное решение @DarioBani.

ansev 10.01.2023 19:20
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
Потяните за рычаг выброса энергососущих проектов
Потяните за рычаг выброса энергососущих проектов
На этой неделе моя команда отменила проект, над которым я работал. Неделя усилий пошла насмарку.
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Привет, люди RPA, это снова я и я несу подарки! В очередном моем приключении о том, как создавать ботов для облегчения рутины. Вот, думаю, стоит...
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
1
3
67
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я хотел бы использовать:

list_to_match = ['a','b','c','d']

# compute a mask of identical values
mask = df.iloc[:, :len(list_to_match)].eq(list_to_match)
# ensure we match values in order
mask2 = mask.cummin(axis=1).sum(axis=1)

# get the rows with max matches
out = df[mask2.eq(mask2.max())]
# or
# out = df.loc[mask2.nlargest(1, keep='all').index]

print(out)

Вывод (игнорируя входную строку 100):

      One Two Three  Four
Index                    
5       a   b     c     g
6       a   b     c  None

Я вижу это как возможное решение, проблема в том, что список имеет переменную длину, например. ['a','b'], в этом случае я считаю, что этот ломается.

Dario Bani 10.01.2023 19:18

Я также изменил основной пост, извиняюсь за поправку

Dario Bani 10.01.2023 19:19

@DarioBani прост в обращении, смотрите обновление

mozway 10.01.2023 19:26

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

Dario Bani 10.01.2023 19:37

@ Дарио, насколько я понимаю, вы хотели исключить строку 100, поскольку она содержала все совпадения, если это неверно, упростите мое решение с помощью: out = df[mask2.eq(mask2.max())] или out = df.loc[mask2.nlargest(1, keep='all').index]

mozway 10.01.2023 19:41

Я определенно злоупотребляю вашим терпением, но есть ли способ, которым я могу нарезать df так, как вы это сделали, добавьте, например, +100 ко всем значениям одного столбца (например, «Шесть») нарезанного фрейма данных, и это влияет на исходный df?

Dario Bani 10.01.2023 19:53

@ Дарио не уверен, что понял, что вы имеете в виду, вы хотите выполнить логическое индексирование? Может стоит открыть дополнительный вопрос?

mozway 10.01.2023 20:14

Вот мой подход. Описания комментируются ниже.

import pandas as pd
import numpy as np
from scipy.spatial.distance import cosine



data = {'One':  ['a', 'a', 'a', 'a'], 
        'Two':  ['b', 'b', 'b', 'b'],
        'Three':  ['c', 'c', 'y', 'c'], 
        'Four': ['g', 'g', 'z', 'd']}

dataframe_ = pd.DataFrame(data)


#encoding Letters into numerical values so we can compute the cosine similarities
dataframe_[:] = dataframe_.to_numpy().astype('<U1').view(np.uint32)-64

#Our input data which we are going to compare with other rows
input_data = np.array(['a', 'b', 'c', 'd'])

#encode input data into numerical values
input_data = input_data.astype('<U1').view(np.uint32)-64

#compute cosine similarity for each row
dataframe_out = dataframe_.apply(lambda row: 1 - cosine(row, input_data), axis=1)
print(dataframe_out)

Выход:

0    0.999343
1    0.999343
2    0.973916
3    1.000000

Фильтрация строк на основе сходства их косинусов:

df_filtered = dataframe_out[dataframe_out.iloc[:, [0]] > 0.99]
print(df_filtered)
0  0.999343
1  0.999343
2       NaN
3  1.000000

Отсюда вы можете легко найти строки со значениями, отличными от NaN, по их индексам.

Другие вопросы по теме