我查了一下这篇文章:在pandas中的数据框中查找非数字行? 但它并没有真正回答我的问题.
我的样本数据:
import pandas as pd
d = {
'unit': ['UD', 'UD', 'UD', 'UD', 'UD','UD'],
'N-D': [ 'Q1', 'Q2', 'Q3', 'Q4','Q5','Q6'],
'num' : [ -1.48, 1.7, -6.18, 0.25, 'sum(d)', 0.25]
}
df = pd.DataFrame(d)
Run Code Online (Sandbox Code Playgroud)
它看起来像这样:
N-D num unit
0 Q1 -1.48 UD
1 Q2 1.70 UD
2 Q3 -6.18 UD
3 Q4 0.25 UD
4 Q5 sum(d) UD
5 Q6 0.25 UD
Run Code Online (Sandbox Code Playgroud)
我想只筛选出'num'列中非NON-NUMERIC的行.我希望所有列只用于包含列'num'的非数字值的行.
期望的输出:
N-D num unit
4 Q5 sum(d) UD
Run Code Online (Sandbox Code Playgroud)
我的尝试:
nonnumeric=df[~df.applymap(np.isreal).all(1)] #didn't work, it pulled out everything, besides i want the condition to check only column 'num'.
nonnumeric=df['num'][~df.applymap(np.isreal).all(1)] #didn't work, it pulled out all the rows for column 'num' only.
Run Code Online (Sandbox Code Playgroud)
jez*_*ael 12
使用boolean indexing由to_numeric+ 创建的掩码
注意:此解决方案找不到或过滤保存为字符串的数字:如'1'或'22'isnull
print (pd.to_numeric(df['num'], errors='coerce'))
0 -1.48
1 1.70
2 -6.18
3 0.25
4 NaN
5 0.25
Name: num, dtype: float64
print (pd.to_numeric(df['num'], errors='coerce').isnull())
0 False
1 False
2 False
3 False
4 True
5 False
Name: num, dtype: bool
print (df[pd.to_numeric(df['num'], errors='coerce').isnull()])
N-D num unit
4 Q5 sum(d) UD
Run Code Online (Sandbox Code Playgroud)
另一种解决方案:isinstance和apply:
print (df[df['num'].apply(lambda x: isinstance(x, str))])
N-D num unit
4 Q5 sum(d) UD
Run Code Online (Sandbox Code Playgroud)
旧主题,但如果数字已转换为“str”,则type(x) == str 不起作用。
相反,最好使用 isnumeric() 或 isdigit()。
df = df[df['num'].apply(lambda x: not x.isnumeric())]
Run Code Online (Sandbox Code Playgroud)
我在自己的数据帧上测试了所有这三种方法,其中包含 200k+ 行,假设数字已被 pd.read_csv() 转换为“str”。
def f1():
df[pd.to_numeric(df['num'], errors='coerce').isnull()]
def f2():
df[~df.num.str.match('^\-?(\d*\.?\d+|\d+\.?\d*)$')]
def f3():
df[df['num'].apply(lambda x: not x.isnumeric())]
Run Code Online (Sandbox Code Playgroud)
通过运行每个函数 10 次,我得到了以下执行时间。
timeit.timeit(f1, number=10)
1.04128568888882
timeit.timeit(f2, number=10)
1.959099448888992
timeit.timeit(f3, number=10)
0.48741375999998127
Run Code Online (Sandbox Code Playgroud)
结论: 最快的方法是isnumeric(),最慢的是正则表达式方法。
==========================================
编辑: 正如@set92 所评论的, isnumeric() 仅适用于整数。所以最快的适用函数是 pd.to_numeric() ,它有一个适用于任何类型数值的通用解决方案。
可以在python中定义一个isfloat()函数;但它会比内部函数慢,特别是对于大数据帧。
tmp=['4.0','4','4.5','1','test']*200000
df=pd.DataFrame(data=tmp,columns=['num'])
def f1():
df[pd.to_numeric(df['num'], errors='coerce').isnull()]
def f2():
df[df['num'].apply(lambda x: not isfloat(x))]
def f3():
df[~df.num.str.match('^\-?(\d*\.?\d+|\d+\.?\d*)$')]
print('to_numeric:',timeit.timeit(f1, number=10))
print('isfloat:',timeit.timeit(f2, number=10))
print('regular exp:',timeit.timeit(f3, number=10))
Run Code Online (Sandbox Code Playgroud)
结果:
to_numeric: 8.303612694763615
isfloat: 9.972200270603594
regular exp: 11.420604273894583
Run Code Online (Sandbox Code Playgroud)