Pandas Dataframe: фильтрация по условию, определенному с использованием столбцов

Я новичок в использовании фреймов данных Pandas, но много использовал фреймы данных Spark. Рассмотрим следующий фрейм данных.

Name   Value   Title
mickey 20      wonderland
donald 10      welcome to donald's castle
minnie 86      Minnie mouse clubhouse

Я хочу сохранить только те строки, где «Имя» содержится в «Заголовке», игнорируя регистр. Итак, в этом случае отфильтрованный фрейм данных должен выглядеть так

Name   Value   Title
donald 10      welcome to donald's castle
minnie 86      Minnie mouse clubhouse

Строка с Name = mickey была удалена.

В искре я могу создать фрейм данных df, а затем сказать df.filter($'Title'.lower().contains($'Name'.lower()))

Есть ли простой способ выразить это в кадрах данных Pandas?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
66
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Строковые методы в pandas по своей природе трудно векторизовать. Я обычно делаю это, используя понимание списка:

df[[y.lower() in x.lower() for x, y in zip(df['Title'], df['Name'])]]

     Name  Value                       Title
1  donald     10  welcome to donald's castle
2  minnie     86      Minnie mouse clubhouse

Большинство строковых методов можно ускорить с помощью понимания списков, если вы не беспокоитесь о NaN и смешанных типах. См. Для петель с пандами - когда мне нужно заботиться?.


Если вам нужна обработка ошибок, используйте функцию с обработкой try-except. Это на все еще быстрее.

def try_check(x, y):
    try:
        return y.lower() in x.lower()
    except AttributeError: 
        return False

df[[try_check(x, y) for x, y in zip(df['Title'], df['Name'])]]

     Name  Value                       Title
1  donald     10  welcome to donald's castle
2  minnie     86      Minnie mouse clubhouse

Вау! Панды серьезно ограничены в плане выразительности. Исходя из мира Spark, манипуляции Pandas DF выглядят почти безобразно. Спасибо за решение, хотя. Это выглядит хорошо. Примет решение.

Nik 30.01.2019 00:13

@Nik pandas не «уродливый» :-), нам просто нужно следовать правильной логике, стоящей за этим.

BENY 30.01.2019 00:16

Использование numpy.core.chararray

s1=df.Title.str.upper().values.astype(str)
s2=df.Name.str.upper().values.astype(str)
df[np.core.chararray.find(s1,s2)!=-1]
Out[790]: 
     Name  Value                       Title
1  donald     10  welcome to donald's castle
2  minnie     86      Minnie mouse clubhouse
Ответ принят как подходящий

Вот еще одно решение, но оно использует метод .apply, не знаю, как это работает с точки зрения скорости, но это работает, и его довольно легко выразить.

df[df.apply(lambda x: x.Name.upper() in x.Title.upper(), axis=1) == True]


# Output
    Name    Value Title
1   donald  10    welcome to donald's castle
2   minnie  86    Minnie mouse clubhouse

Вот еще несколько вариантов, все основаны на этот ТАК пост (главное требование — использовать "|".join(...))

Вариант 1 — df.query()

df_match = df.query("Title.str.lower().str.contains('|'.join(Name.str.lower()))")
print(df_match)
     Name  Value                       Title
1  donald     10  welcome to donald's castle
2  minnie     86      Minnie mouse clubhouse

вариант 2

print(df[df['Title'].str.lower().str.contains('|'.join(df['Name'].str.lower()))])
     Name  Value                       Title
1  donald     10  welcome to donald's castle
2  minnie     86      Minnie mouse clubhouse

вариант 3 — с использованием NumPy where

from numpy import where
df['match'] = (
                where(df.Title.str.lower().str.contains(
                    '|'.join(df['Name'].str.lower()))
                , True, False)
                )
print(df[df['match']==True])
     Name  Value                       Title  match
1  donald     10  welcome to donald's castle   True
2  minnie     86      Minnie mouse clubhouse   True

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