【发布时间】:2019-08-17 12:17:17
【问题描述】:
我有一个数据框,其中一列是 df['Names']。如何找到名称以小写字母开头的所有行?
col1 Names
1564 abby
2289 Barry
等等
我正在尝试使用正则表达式来完成此操作,但没有成功。
【问题讨论】:
我有一个数据框,其中一列是 df['Names']。如何找到名称以小写字母开头的所有行?
col1 Names
1564 abby
2289 Barry
等等
我正在尝试使用正则表达式来完成此操作,但没有成功。
【问题讨论】:
来自str.lower的一种方式
df[df.Names.str[0]==df.Names.str[0].str.lower()]
Out[173]:
col1 Names
0 1564 abby
另一种方式islower
df[df.Names.str[0].str.islower()]
Out[174]:
col1 Names
0 1564 abby
【讨论】:
islower 的问题是它仅在所有字符都较低时才返回True,而不仅仅是第一个字符
df[df.col.str[0].str.islower()] 冒昧编辑了。
如果我们谈论性能,那么 NumPy 怎么样?将系列转换为字符串数组,提取第一个字符并比较 ASCII 值。
a = df['Names'].values.astype('<S1').view(np.int8)
df[(a >= 97) & (a <= 122)]
col1 Names
0 1564 abby
如果您只需要索引,请使用 np.nonzero:
(a >= 97) & (a <= 122)
# array([ True, False])
np.flatnonzero((a >= 97) & (a <= 122))
# array([0])
【讨论】:
一种使用string.ascii_lowercase的方式
import string
df.loc[df.Names.str[0].isin(list(string.ascii_lowercase))]
使用regex的另一种方式
df[df.col.str.match('[a-z].*')]
一些时间
df = pd.DataFrame({'col': ['abc', 'Abc', 'dce', 'ADAE']})
df = pd.concat([df]*100)
%%timeit
a = df['col'].values.astype('<S1').view(np.int8)
df[(a >= 97) & (a <= 122)]
302 µs ± 21.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df.col.str[0].isin(list(string.ascii_lowercase))
548 µs ± 13 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df[df.col.str.islower()]
559 µs ± 28.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df[df.col.str.match('[a-z].*')]
838 µs ± 17.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df[df.col.str[0]==df.col.str[0].str.lower()]
1.59 ms ± 65 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
【讨论】:
isin 这里的性能实际上优于惯用的 is_lower() 函数,这很酷(阅读:有趣)。
isin 最好使用列表作为 arg 而不是 set。大熊猫的一大谜团(我想jpp 前段时间问过这个问题)