Python Pandas-标识以列表中的值开头的数据帧值

Python Pandas-标识以列表中的值开头的数据帧值,python,pandas,Python,Pandas,假设我有以下数据帧: >>> 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

假设我有以下数据帧:

>>> 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
和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
,然后
unstack
返回到原始形式:

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
相比,这是一种更干净的方法。您可以这样做:

d.applymap(lambda x: any([x.startswith(v) for v in vals]))

替代解决方案,不使用
.apply()


有点复杂,但这似乎是最快的解决方案

您可以使用仅适用于系列的,因此请使用
list
理解和输出。但是需要检查列表
VAL
中的更多项目,因此使用另一个列表理解和
reduce
,它与
numpy数组一起工作
-转换
concat
的输出,最后创建
Dataframe
,列和索引与原始列和索引相同,数据是
numpy的输出。逻辑\u或

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
您可以执行
df.apply(lambda x:x.str.contains('|'.join(vals)))
#[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