Pandas:判断一列中的字符串是否是另一列中字符串的子串
Pandas: Determine if a string in one column is a substring of a string in another column
考虑这些系列:
>>> a = pd.Series('abc a abc c'.split())
>>> b = pd.Series('a abc abc a'.split())
>>> pd.concat((a, b), axis=1)
0 1
0 abc a
1 a abc
2 abc abc
3 c a
>>> unknown_operation(a, b)
0 False
1 True
2 True
3 False
所需的逻辑是确定左列中的字符串是否是右列中字符串的子字符串。 pd.Series.str.contains
不接受另一个系列,pd.Series.isin
检查该值是否存在于另一个系列中(具体不在同一行)。我很想知道是否有矢量化解决方案(不使用 .apply
或循环),但可能没有。
IIUC,
df[1].str.split('', expand=True).eq(df[0], axis=0).any(axis=1) | df[1].eq(df[0])
输出:
0 False
1 True
2 True
3 False
dtype: bool
让我们尝试使用矢量化的 numpy
defchararray
from numpy.core.defchararray import find
find(df['1'].values.astype(str),df['0'].values.astype(str))!=-1
Out[740]: array([False, True, True, False])
我使用随机生成的包含 1,000,000 个 5 个字母条目的 Dataframe 测试了各种功能。
运行 在我的机器上,3 次测试的平均值显示:
zip > v_find > to_list > 任意 > 应用
0.21s > 0.79s > 1s > 3.55s > 8.6s
因此,我建议使用 zip:
[x[0] in x[1] for x in zip(df['A'], df['B'])]
或矢量化查找(由 BENY 提出)
np.char.find(df['B'].values.astype(str), df['A'].values.astype(str)) != -1
我的测试设置:
def generate_string(length):
return ''.join(random.choices(string.ascii_uppercase + string.digits, k=length))
A = [generate_string(5) for x in range(n)]
B = [generate_string(5) for y in range(n)]
df = pd.DataFrame({"A": A, "B": B})
to_list = pd.Series([a in b for a, b in df[['A', 'B']].values.tolist()])
apply = df.apply(lambda s: s["A"] in s["B"], axis=1)
v_find = np.char.find(df['B'].values.astype(str), df['A'].values.astype(str)) != -1
any = df["B"].str.split('', expand=True).eq(df["A"], axis=0).any(axis=1) | df["B"].eq(df["A"])
zip = [x[0] in x[1] for x in zip(df['A'], df['B'])]
考虑这些系列:
>>> a = pd.Series('abc a abc c'.split())
>>> b = pd.Series('a abc abc a'.split())
>>> pd.concat((a, b), axis=1)
0 1
0 abc a
1 a abc
2 abc abc
3 c a
>>> unknown_operation(a, b)
0 False
1 True
2 True
3 False
所需的逻辑是确定左列中的字符串是否是右列中字符串的子字符串。 pd.Series.str.contains
不接受另一个系列,pd.Series.isin
检查该值是否存在于另一个系列中(具体不在同一行)。我很想知道是否有矢量化解决方案(不使用 .apply
或循环),但可能没有。
IIUC,
df[1].str.split('', expand=True).eq(df[0], axis=0).any(axis=1) | df[1].eq(df[0])
输出:
0 False
1 True
2 True
3 False
dtype: bool
让我们尝试使用矢量化的 numpy
defchararray
from numpy.core.defchararray import find
find(df['1'].values.astype(str),df['0'].values.astype(str))!=-1
Out[740]: array([False, True, True, False])
我使用随机生成的包含 1,000,000 个 5 个字母条目的 Dataframe 测试了各种功能。
运行 在我的机器上,3 次测试的平均值显示:
zip > v_find > to_list > 任意 > 应用
0.21s > 0.79s > 1s > 3.55s > 8.6s
因此,我建议使用 zip:
[x[0] in x[1] for x in zip(df['A'], df['B'])]
或矢量化查找(由 BENY 提出)
np.char.find(df['B'].values.astype(str), df['A'].values.astype(str)) != -1
我的测试设置:
def generate_string(length):
return ''.join(random.choices(string.ascii_uppercase + string.digits, k=length))
A = [generate_string(5) for x in range(n)]
B = [generate_string(5) for y in range(n)]
df = pd.DataFrame({"A": A, "B": B})
to_list = pd.Series([a in b for a, b in df[['A', 'B']].values.tolist()])
apply = df.apply(lambda s: s["A"] in s["B"], axis=1)
v_find = np.char.find(df['B'].values.astype(str), df['A'].values.astype(str)) != -1
any = df["B"].str.split('', expand=True).eq(df["A"], axis=0).any(axis=1) | df["B"].eq(df["A"])
zip = [x[0] in x[1] for x in zip(df['A'], df['B'])]