簡體   English   中英

Pandas 過濾器 dataframe 列通過 substring 匹配

[英]Pandas filter dataframe columns through substring match

我有一個帶有多列的 dataframe,例如:

     Name  Age   Fname
0    Alex   10   Alice
1     Bob   12     Bob
2  Clarke   13  clarke

我的過濾條件是檢查Name是否(不區分大小寫) substring 對應的Fname

如果它是平等的,那么簡單的事情就是:

df[df["Name"].str.lower() == df["Fname"].str.lower()]

作品。 但是,我想要 substring 匹配,所以我想代替== ,我認為in會起作用。 但這會產生錯誤,因為它將 arguments 之一解釋為pd.Series 我的第一個問題是Why this difference in interpretation?

我嘗試的另一種方法是使用.str.contains

df[df["Fname"].str.contains(df["Name"], case=False)]

它也將df["Name"]解釋為pd.Series ,當然,它適用於參數中的一些 const 字符串。

eg. this works:
df[df["Fname"].str.contains("a", case=False)]

我想解決這種情況,因此感謝您提供這方面的任何幫助。

.str 訪問器非常循環和緩慢。 大多數時候最好使用列表理解。

import pandas as pd
import numpy as np
import timeit
import matplotlib.pyplot as plt
import pandas.testing as pt

def list_comprehension_lower(df):
    return df[[len(set(i)) == 1 for i in (zip([x.lower() for x in df['Name']],[y.lower() for y in df['Fname']]))]]

def apply_axis_1_lower(df):
    return df[df.apply(lambda x: x['Name'].lower() in x['Fname'].lower(), axis=1)]

def dot_string_lower(df):
    return df[df["Name"].str.lower() == df["Fname"].str.lower()]

fig, ax = plt.subplots()
res = pd.DataFrame(
    index=[1, 5, 10, 30, 50, 100, 300, 500, 700, 1000, 10000],
    columns='list_comprehension_lower apply_axis_1_lower dot_string_lower'.split(),
    dtype=float
)

for i in res.index:
    d = pd.concat([df]*i, ignore_index=True)
    for j in res.columns:
        stmt = '{}(d)'.format(j)
        setp = 'from __main__ import d, {}'.format(j)
        res.at[i, j] = timeit.timeit(stmt, setp, number=100)

res.groupby(res.columns.str[4:-1], axis=1).plot(loglog=True, ax=ax);

Output:

在此處輸入圖像描述

現在,回到你原來的問題,你可以使用 list_comprehension 和zip in

df.loc[2, 'Fname'] += ' Adams'

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

Output:

     Name  Age         Fname
1     Bob   12           Bob
2  Clarke   13  clarke Adams

您可以使用.apply()axis=1為每一行調用 function :

subset = df[df.apply(lambda x: x['Name'].lower() in x['Fname'].lower(), axis=1)]

Output:

>>> subset
     Name  Age   Fname
1     Bob   12     Bob
2  Clarke   13  clarke

您可以遍歷索引軸:

>>> df[df.apply(lambda x: x['Name'].lower() in x['Fname'].lower(), axis=1)]

     Name  Age   Fname
1     Bob   12     Bob
2  Clarke   13  clarke

str.contains在第一個參數pat中采用常量而不是Series

通過列表理解的其他選項是否適合您:

df.loc[[left.lower() in right.lower() 
        for left, right 
        in zip(df.Name, df.Fname)]
       ]

     Name  Age   Fname
1     Bob   12     Bob
2  Clarke   13  clarke

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM