说我有以下数据框:
>>> vals=['123','76']
并说我有3个感兴趣的值:
>>> d.isin(vals)
A B C
0 False False False
1 False False False
2 True False False
3 False False False
>>>
我有兴趣确定数据框中的哪些值以列表中的任何值开头。在我的例子中有3个案例:(0,A)以123开头; (1,A)以123开头; (2,A)以76开头。
有没有办法可以在不循环遍历每个值的情况下执行此操作?
如果我对匹配值感兴趣,我可以这样做:
>>> d.applymap(lambda x:x.startswith('123'))
A B C
0 True False False
1 True False False
2 False False False
3 False False False
>>>
如果我对这些值是否以1个特定值开始感兴趣,我可以这样做:
{{1}}
但是如何将这两者结合起来找到以列表中的任何值开头的任何值?
答案 0 :(得分:3)
你可以这样做:
d.applymap(lambda x: any([x.startswith(v) for v in vals]))
答案 1 :(得分:1)
替代解决方案,它不使用.apply()
:
In [66]: search_re = '^(?:{})'.format('|'.join(vals))
In [67]: search_re
Out[67]: '^(?:123|76)'
In [69]: df.astype(str).stack().str.match(search_re).unstack()
Out[69]:
A B C
0 True False False
1 True False False
2 True False False
3 False False False
答案 2 :(得分:0)
有点复杂,但似乎是最快的解决方案。
您可以使用仅适用于系列的str.startswith
,因此请使用list
理解和concat
输出。但是需要检查列表vals
中的更多项目,因此请使用numpy.logical_or
与reduce
合并numpy array
的其他列表理解 - 转换concat
的输出并最后创建Dataframe
具有与原始列表和索引相同的列和索引numpy.logical_or
:
print ([pd.concat([d[col].str.startswith(i) for col in d], axis=1).values for i in vals])
[array([[ True, False, False],
[ True, False, False],
[False, False, False],
[False, False, False]], dtype=bool), array([[False, False, False],
[False, False, False],
[ True, False, False],
[False, False, False]], dtype=bool)]
print (np.logical_or.reduce(
[pd.concat([d[col].str.startswith(i) for col in d], axis=1).values for i in vals]))
[[ True False False]
[ True False False]
[ True False False]
[False False False]]
print(pd.DataFrame(np.logical_or.reduce(
[pd.concat([d[col].strstartswith(i) for col in d],
axis=1).values for i in vals]),
index=d.index, columns=d.columns))
A B C
0 True False False
1 True False False
2 True False False
3 False False False
<强>计时强>:
#[40000 rows x 3 columns]
d = pd.concat([d]*10000).reset_index(drop=True)
In [77]: %timeit (d.applymap(lambda x: any([x.startswith(v) for v in vals])))
1 loop, best of 3: 228 ms per loop
In [78]: %timeit (d.apply(lambda x: x.str.contains('|'.join(['^' + x for x in vals]))))
10 loops, best of 3: 147 ms per loop
In [79]: %timeit (d.astype(str).stack().str.match('^(?:{})'.format('|'.join(vals))).unstack())
10 loops, best of 3: 172 ms per loop
In [80]: %timeit (pd.DataFrame(np.logical_or.reduce([pd.concat([d[col].str.startswith(i) for col in d], axis=1).values for i in vals]), index=d.index, columns=d.columns))
10 loops, best of 3: 116 ms per loop