[英]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.