#python #pandas #dataframe
#питон #панды #фрейм данных
Вопрос:
У меня есть подмножество фрейма данных
df = pd.DataFrame( { 'id': ['1001','1002','1003','1004','1005','1006','1007','1008','1009','1010'], 'colA': ['H','L B','L H','L B','L S B','B','B S L','L B S','L S B','L S B'], 'colB': ['H','L|B','H|L','H|L','L|S|B','L|S|B','L|S|B','L|S|B','L|S','L'] } )
Я провожу сравнение уровня строк для этого фрейма данных. Я хочу проверить , совпадают ли все буквы в row['colA']
со всеми буквами в row['colB']
, независимо от того, в каком порядке они появляются, и игнорируя |
colB
ввод . Это логика для функции, но она работает не так, как предполагалось, и как мне обновить ее, чтобы игнорировать |
def match_or_not(df): for index,row in df.iterrows(): if row['colA'] == row['colB']: print ("Match for " str(row['id'])) else: print ("Not match for " str(row['id']))
Мне нужна помощь, чтобы обновить условие после if
ключевого слова в приведенной выше функции, как я могу написать, чтобы получить желаемый результат. Случаи, для которых он должен совпадать и не совпадать, показаны на рисунке:
Ответ №1:
Должно сработать следующее:
def match_or_not(df): for index,row in df.iterrows(): #First make a list out of the values, then compare the sorted values if sorted(row['colA'].split(" ")) == (sorted(row['colB'].split("|"))): print ("Match for " str(row['id'])) else: print ("Not match for " str(row['id']))
Ответ №2:
Вы можете использовать метод «split()» для строк, а также наборов, например:
def match_or_not(df): for index,row in df.iterrows(): a_set = set(row['colA'].split(" ")) b_set = set(row['colB'].split("|")) if a_set == b_set: print ("Match for " str(row['id'])) else: print ("Not match for " str(row['id']))
split()
создает список подстрок, используя заданный разделитель (в вашем случае пробел и a |
).
set()
делает этот список набором. Наборы легко сравнивать, так как порядок в них не имеет значения. Однако это решение имеет потенциальный недостаток, который не отражен в данных вашего примера:
set("L L".split(" "))
Это разбивает строку L L
, которая создает список из двух строк «L». Однако элементы набора уникальны, поэтому он преобразуется в набор {'L'}
(имейте в виду только один L.)
Поэтому, если ожидается, что ваши данные будут содержать такие двойные строки и их появление должно совпадать по количеству, этого решения недостаточно.
Ответ №3:
Вы можете использовать df.apply
без df.iterrows()
:
gt;gt;gt; df.apply(lambda row: f"Match for {row['id']}" if set(row['colA'].replace(" ", "")) == set(row['colB'].replace("|", "")) else f"No match for {row['id']}", axis=1) 0 Match for 1001 1 Match for 1002 2 Match for 1003 3 No match for 1004 4 Match for 1005 5 No match for 1006 6 Match for 1007 7 Match for 1008 8 No match for 1009 9 No match for 1010
set(row['colA'].replace(" ", "")) == set(row['colB'].replace("|", ""))
Условие гарантирует, что все символы, кроме пробелов из colA
, существуют в colB
(кроме |
символов, все пробелы и каналы удаляются перед преобразованием в a set
).
Комментарии:
1. Извините, но для этого не требуется, метод all() проверяет, все ли элементы A содержатся в B, а не совпадают ли два столбца. Но df подать заявку-это определенно правильный путь!
2. @AchilleG Вы правы, я пропустил часть, чтобы убедиться, что у них обоих одинаковые символы. Я немного изменил решение
set
, теперь оно дает ожидаемый результат. На самом деле изображение операционной системы отличается от предоставленных данных.