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