说我有以下数据帧:
>>> import pandas as pd
>>> d=pd.DataFrame()
>>> d['A']=['12345','12354','76','4']
>>> d['B']=['4442','2345','33','5']
>>> d['C']=['5553','4343','33','5']
>>> d
A B C
0 12345 4442 5553
1 12354 2345 4343
2 76 33 33
3 4 5 5
并说我有3个感兴趣的值:
>>> vals=['123','76']
我有兴趣确定我的数据框中的哪些值以列表中的任何值开头.在我的例子中有3个案例:(0,A)以123开头; (1,A)以123开头; (2,A)以76开头.
有没有办法可以做到这一点而不循环我的每个值?
如果我对匹配值感兴趣,我可以这样做:
>>> d.isin(vals)
A B C
0 False False False
1 False False False
2 True False False
3 False False False
>>>
如果我对值是否从1个特定值开始感兴趣,我可以这样做:
>>> 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
>>>
但是,如何将这两个结合起来找到以列表中的任何值开头的任何值?
最佳答案 您可以使用apply with lambda调用str.contains来构造正则表达式模式并依次测试每个列:
In [9]:
vals=['123','76']
v = ['^' + x for x in vals]
d.apply(lambda x: x.str.contains('|'.join(v)))
Out[9]:
A B C
0 True False False
1 True False False
2 True False False
3 False False False
由此产生的正则表达式模式:
In [10]:
'|'.join(v)
Out[10]:
'^123|^76'
更新
实际上你可以使用stack和unstack来做到这一点,这样你最初可以将所有列堆叠到一个列中,用正则表达式模式调用str.contains然后取消堆栈回原始形式:
In [9]:
vals=['123','76']
v = ['^' + x for x in vals]
d.stack().str.contains('|'.join(v)).unstack()
Out[9]:
A B C
0 True False False
1 True False False
2 True False False
3 False False False
与使用apply相比,这是一种更简洁的方法