我有一个像这样的数据框
import pandas as pd
df = pd.DataFrame({'a': ['abc', 'r00001', 'r00010', 'rfoo', 'r01234', 'r1234'], 'b': range(6)})
a b
0 abc 0
1 r00001 1
2 r00010 2
3 rfoo 3
4 r01234 4
5 r1234 5
我现在想要选择此数据框的所有列,其中a
列中的条目以r
开头,后跟五个数字。
From here我学会了如果只使用r
而没有数字的话就会这样做:
print df.loc[df['a'].str.startswith('r'), :]
a b
1 r00001 1
2 r00010 2
3 rfoo 3
4 r01234 4
5 r1234 5
像这样的东西
print df.loc[df['a'].str.startswith(r'[r]\d{5}'), :]
当然不起作用。如何正确地做到这一点?
答案 0 :(得分:5)
df.a.str.match('^r\d{5}$')
1 True
2 True
3 False
4 True
5 False
Name: a, dtype: bool
将其用作过滤器
df[df.a.str.match('^r\d{5}$')]
a b
1 r00001 1
2 r00010 2
4 r01234 4
选项2
使用字符串方法的自定义列表理解
f = lambda s: s.startswith('r') and (len(s) == 6) and s[1:].isdigit()
[f(s) for s in df.a.values.tolist()]
[False, True, True, False, True, False]
将其用作过滤器
df[[f(s) for s in df.a.values.tolist()]]
a b
1 r00001 1
2 r00010 2
4 r01234 4
计时
df = pd.concat([df] * 10000, ignore_index=True)
%timeit df[[s.startswith('r') and (len(s) == 6) and s[1:].isdigit() for s in df.a.values.tolist()]]
%timeit df[df.a.str.match('^r\d{5}$')]
%timeit df[df.a.str.contains('^r\d{5}$')]
10 loops, best of 3: 22.8 ms per loop
10 loops, best of 3: 33.8 ms per loop
10 loops, best of 3: 34.8 ms per loop
答案 1 :(得分:5)
您可以使用str.contains
并传递正则表达式模式:
In[112]:
df.loc[df['a'].str.contains(r'^r\d{5}')]
Out[112]:
a b
1 r00001 1
2 r00010 2
4 r01234 4
此处模式评估为^r
- 以字符r开头,然后\d{5}
查找5位
startswith
查找字符模式,而不是正则表达式模式,这就是失败的原因
关于str.contains
和str.match
之间的区别,它们是偶然的,str.contains
使用re.search
而str.match
使用re.match
更严格,请参阅docs。
修改强>
要回复您的评论,请添加$
以使其与特定数量的字符匹配,请参阅related:
In[117]:
df = pd.DataFrame({'a': ['abc', 'r000010', 'r00010', 'rfoo', 'r01234', 'r1234'], 'b': range(6)})
df
Out[117]:
a b
0 abc 0
1 r000010 1
2 r00010 2
3 rfoo 3
4 r01234 4
5 r1234 5
In[118]:
df.loc[df['a'].str.match(r'r\d{5}$')]
Out[118]:
a b
2 r00010 2
4 r01234 4