【问题标题】:get non numerical rows in a column pandas python获取列中的非数字行 pandas python
【发布时间】:2017-10-23 17:48:22
【问题描述】:

我查看了这个帖子:finding non-numeric rows in dataframe in 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)

看起来像这样:

  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

我只想过滤掉“num”列中非数字的行。我只想要包含列“num”的非数字值的行的所有列。

想要的输出:

  N-D   num   unit
4  Q5   sum(d) UD

我的尝试:

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.

【问题讨论】:

  • non_num_rows = list(df[pd.to_numeric(df['num'], errors='coerce').isnull()].index)

标签: python pandas


【解决方案1】:

boolean indexingto_numeric + isnull 创建的掩码一起使用
注意:此解决方案不会查找或过滤保存为字符串的数字:例如 '1' 或 '22'

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

isinstanceapply 的另一种解决方案:

print (df[df['num'].apply(lambda x: isinstance(x, str))])
  N-D     num unit
4  Q5  sum(d)   UD

【讨论】:

    【解决方案2】:

    老话题,但如果数字已转换为 'str',type(x) == str 不起作用。

    相反,最好使用 isnumeric() 或 isdigit()。

    df = df[df['num'].apply(lambda x: not x.isnumeric())]
    

    假设数字已通过 pd.read_csv() 转换为“str”,我在自己的数据帧上测试了所有三种方法,其中包含 200k+ 行。

    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())]
    

    我通过运行每个函数 10 次得到以下执行时间。

    timeit.timeit(f1, number=10)
    1.04128568888882
    
    timeit.timeit(f2, number=10)
    1.959099448888992
    
    timeit.timeit(f3, number=10)
    0.48741375999998127
    

    推断: fastest 方法是 isnumeric(),slowest 是正则表达式方法。

    ==========================================

    编辑: 正如@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))
    

    结果:

    to_numeric: 8.303612694763615
    isfloat: 9.972200270603594
    regular exp: 11.420604273894583
    

    【讨论】:

    • 应该不行,df['num'] 是浮点数,isnumeric() 和 isdigit() 只对整数有效。我正在搜索一些函数,但似乎唯一可用的解决方案是创建一个函数 def isfloat(value): try: float(value) return True except ValueError: return False,然后将您的解决方案更改为 df['num'].loc[df['num'].apply(lambda x: not isfloat(x))]
    • 但是 pd.to_numeric() 可以正常工作。这是一个内部函数,速度很快。无需定义函数!
    • 使用 pd.to_numeric 我得到了一个错误字符串 (ValueError: Unable to parse string "Unrated" at position 32)。如果您想尝试数据集是kaggle 的拉面评级。但问题是功能 Stars 有浮点数和 3 个带有“未分级”的单元格,所以我找不到一行来应用它并找到有多少行不是数字。
    • 您应该使用pd.to_numeric(... ,errors='coerce') 跳过错误
    【解决方案3】:

    我用过

    df = df[df['num'].apply(lambda x: type(x) == str)]
    

    现在 df 是

      N-D     num unit
    4  Q5  sum(d)   UD
    

    【讨论】:

      【解决方案4】:

      假设这些是字符串,您可以根据浮点数的正则表达式匹配进行过滤。

      df[~df.num.str.match('^\-?(\d*\.?\d+|\d+\.?\d*)$')]
      
        N-D     num unit
      4  Q5  sum(d)   UD
      

      【讨论】:

        【解决方案5】:

        在pandas DataFrame的列中检测非数值的方法有很多,这里有一种。

        df[~df['num'].map(lambda x:x.isnumeric())]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-25
          相关资源
          最近更新 更多