Pandas 查找字段A是字段B的子字符串的行

Pandas 查找字段A是字段B的子字符串的行,pandas,Pandas,有两列关键字和字符串的10 mil记录 我想查找关键字列出现在其字符串列中的行: test_df=pd.DataFrame({'keyword1':['day','night','internet','day','night','internet'],'string1':['today is a good day','I like this','youtube','sunday','what is this','internet']}) test_df 我的第一次尝试是使用。应用,但速度很慢

有两列
关键字
字符串
的10 mil记录

我想查找
关键字
列出现在其
字符串
列中的行:

test_df=pd.DataFrame({'keyword1':['day','night','internet','day','night','internet'],'string1':['today is a good day','I like this','youtube','sunday','what is this','internet']})
test_df

我的第一次尝试是使用。应用,但速度很慢

test_df[test_df.apply(lambda x: True if x['keyword1'] in x['string1'] else False,axis=1)]
因为有10毫升不同的字符串,但关键字的数量非常少(数量级为1万)。所以我在想,如果我按关键字分组,可能会更有效率

test_df.groupby('keyword1',group_keys=False).apply(lambda x: x[x['string1'].str.contains(x.loc[x.index[0],'keyword1'])])
据推测,这种方法只有10万次迭代,而不是10万次迭代。但它只是稍微快一点(10%)。我不知道为什么?迭代的开销很小,或者groupby有其额外的成本


我的问题是:有没有更好的方法来完成这项工作?

一个想法是创建mask by并通过
x.name
进行比较,同样
regex=False
应该可以提高性能,但这里似乎仍然有很多组(10k),因此
groupby
是这里的瓶颈:

mask = (test_df.groupby('keyword1')['string1']
               .transform(lambda x : x.str.contains(x.name, regex=False)))

df = test_df[mask]
print (df)
   keyword1              string1
0       day  today is a good day
3       day               sunday
5  internet             internet
另一个想法是使用列表理解,但不确定10米是否更快:

test_df[[x in y for x, y in test_df[['keyword1','string1']].to_numpy()]]
有些测试使用样本数据,但这里只有少数几个组,因此
groupby
非常快:

#6k data
test_df = pd.concat([test_df] * 1000, ignore_index=True)

In [49]: %timeit test_df[test_df.groupby('keyword1', sort=False)['string1'].transform(lambda x :x.str.contains(x.name, regex=False))]
5.84 ms ± 265 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [50]: %timeit test_df[[x in y for x, y in test_df[['keyword1','string1']].to_numpy()]]
9.46 ms ± 47.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


请参考下面的链接。也许这会有帮助,谢谢,这是一篇非常有趣的帖子。但是我认为我的用例比这个简单一点,现在我不想使用NLP来实现这个。谢谢。因此,groupby.transform似乎比groupby.apply更快。在我的实际应用程序中,我有两个关键字,包含其中任何一个都被认为是匹配的。因此,我的最后一段代码如下所示:df[df.groupby(['keyword1','keyword2'])['string'].transform(lambda x:x.str.contains(x.name[0],regex=False)| x.str.contains(x.name[1],regex=False))]。我将if与最初的方法进行了比较,对于10密耳行,它是183秒对220秒和312秒。这是一个有意义的改进,但仍然需要3分钟。可能是因为有很多团体。@YuanRen-我同意,还有很多团体。@YuanRen-应该有一个想法-试试看
In [51]: %timeit test_df.groupby('keyword1',group_keys=False).apply(lambda x: x[x['string1'].str.contains(x.loc[x.index[0],'keyword1'])])
11.7 ms ± 204 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [52]: %timeit test_df[test_df.apply(lambda x: True if x['keyword1'] in x['string1'] else False,axis=1)]
138 ms ± 887 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)