【问题标题】:Removing nan values from an array从数组中删除 nan 值
【发布时间】:2012-07-22 04:24:29
【问题描述】:

我想弄清楚如何从我的数组中删除 nan 值。我的数组看起来像这样:

x = [1400, 1500, 1600, nan, nan, nan ,1700] #Not in this exact configuration

如何从x 中删除nan 值?

【问题讨论】:

  • 明确地说,“删除 NaN”是指仅过滤掉非空值的子集。不是“用某个值(零、常数、平均值、中位数等)填充 NaN”

标签: python arrays numpy nan


【解决方案1】:

如果您对数组使用 numpy,您也可以使用

x = x[numpy.logical_not(numpy.isnan(x))]

等价

x = x[~numpy.isnan(x)]

[感谢 chbrown 添加的速记]

说明

内部函数numpy.isnan 返回一个布尔/逻辑数组,在x 不是数字的任何地方都有值True。正如我们想要的相反,我们使用逻辑非运算符 ~ 来获取一个数组,其中包含 Trues 的所有 x 一个有效数字。

最后我们使用这个逻辑数组来索引原始数组x,只检索非NaN值。

【讨论】:

  • x = x[numpy.isfinite(x)]
  • x = x[~numpy.isnan(x)],相当于mutzmatron的原始答案,但更短。如果你想保持无穷大,当然知道numpy.isfinite(numpy.inf) == False,但是~numpy.isnan(numpy.inf) == True
  • 对于希望使用 ndarray 解决此问题并保持尺寸的人,请使用 numpy where:np.where(np.isfinite(x), x, 0)
  • TypeError: 只有整数标量数组可以转换为标量索引
  • @towry:这是因为您的输入 x 不是一个 numpy 数组。如果你想使用逻辑索引,它必须是一个数组——例如x = np.array(x)
【解决方案2】:
filter(lambda v: v==v, x)

适用于列表和 numpy 数组 因为 v!=v 仅适用于 NaN

【讨论】:

  • 一种技巧,但在您从具有混合类型的对象数组(例如字符串和 nans)中过滤 nans 的情况下特别有用。
  • 非常干净的解决方案。
  • 这可能看起来很聪明,但如果逻辑模糊,理论上其他对象(例如自定义类)也可以具有此属性
  • 也很有用,因为它只需要指定一次x,而不是x[~numpy.isnan(x)] 类型的解决方案。当x 由长表达式定义并且您不想通过创建临时变量来存储该长表达式的结果而使代码混乱时,这很方便。
  • x[~numpy.isnan(x)] 可能会比较慢
【解决方案3】:

试试这个:

import math
print [value for value in x if not math.isnan(value)]

更多信息,请阅读List Comprehensions

【讨论】:

  • 如果你使用 numpy 我的答案和@lazy1 的答案几乎比列表理解快一个数量级 -lazy1 的解决方案稍微快一些(尽管从技术上讲也不会返回任何无穷大值) .
  • 别忘了括号 :) print ([value for value in x if not math.isnan(value)])
  • 如果您使用像最佳答案一样的 numpy,那么您可以将此列表理解答案与 np 包一起使用:所以返回没有 nans 的列表:[value for value in x if not np.isnan(value)]
【解决方案4】:

@jmetz 的回答对我来说不起作用,但是使用 pandas isnull() 可以。

x = x[~pd.isnull(x)]

【讨论】:

    【解决方案5】:

    如别人所见

    x[~numpy.isnan(x)]
    

    有效。但如果 numpy dtype 不是本机数据类型,例如它是对象,它将引发错误。在这种情况下,您可以使用 pandas。

    x[~pandas.isna(x)] or x[~pandas.isnull(x)]
    

    【讨论】:

      【解决方案6】:

      @jmetz's answer 可能是大多数人需要的;但是它会产生一个一维数组,例如使其无法删除矩阵中的整行或整列。

      为此,应将逻辑数组缩减为一维,然后索引目标数组。例如,以下将删除至少具有一个 NaN 值的行:

      x = x[~numpy.isnan(x).any(axis=1)]
      

      查看更多详情here

      【讨论】:

        【解决方案7】:

        执行上述操作:

        x = x[~numpy.isnan(x)]
        

        x = x[numpy.logical_not(numpy.isnan(x))]
        

        我发现重置为相同的变量 (x) 并没有删除实际的 nan 值,并且必须使用不同的变量。将其设置为不同的变量会删除 nans。 例如

        y = x[~numpy.isnan(x)]
        

        【讨论】:

        • 这很奇怪;根据the docs,布尔数组索引(这是)在高级索引下,显然“总是返回数据的副本”,所以你应该用x覆盖新值(即没有 NaN...)。您能否提供更多信息说明为什么会发生这种情况?
        【解决方案8】:

        如果您使用的是numpy

        # first get the indices where the values are finite
        ii = np.isfinite(x)
        
        # second get the values
        x = x[ii]
        

        【讨论】:

          【解决方案9】:

          accepted answer 改变二维数组的形状。 我在这里提出了一个解决方案,使用 Pandas dropna() 功能。 它适用于一维和二维数组。在 2D 情况下,您可以选择天气来删除包含np.nan 的行或列

          import pandas as pd
          import numpy as np
          
          def dropna(arr, *args, **kwarg):
              assert isinstance(arr, np.ndarray)
              dropped=pd.DataFrame(arr).dropna(*args, **kwarg).values
              if arr.ndim==1:
                  dropped=dropped.flatten()
              return dropped
          
          x = np.array([1400, 1500, 1600, np.nan, np.nan, np.nan ,1700])
          y = np.array([[1400, 1500, 1600], [np.nan, 0, np.nan] ,[1700,1800,np.nan]] )
          
          
          print('='*20+' 1D Case: ' +'='*20+'\nInput:\n',x,sep='')
          print('\ndropna:\n',dropna(x),sep='')
          
          print('\n\n'+'='*20+' 2D Case: ' +'='*20+'\nInput:\n',y,sep='')
          print('\ndropna (rows):\n',dropna(y),sep='')
          print('\ndropna (columns):\n',dropna(y,axis=1),sep='')
          
          print('\n\n'+'='*20+' x[np.logical_not(np.isnan(x))] for 2D: ' +'='*20+'\nInput:\n',y,sep='')
          print('\ndropna:\n',x[np.logical_not(np.isnan(x))],sep='')
          

          结果:

          ==================== 1D Case: ====================
          Input:
          [1400. 1500. 1600.   nan   nan   nan 1700.]
          
          dropna:
          [1400. 1500. 1600. 1700.]
          
          
          ==================== 2D Case: ====================
          Input:
          [[1400. 1500. 1600.]
           [  nan    0.   nan]
           [1700. 1800.   nan]]
          
          dropna (rows):
          [[1400. 1500. 1600.]]
          
          dropna (columns):
          [[1500.]
           [   0.]
           [1800.]]
          
          
          ==================== x[np.logical_not(np.isnan(x))] for 2D: ====================
          Input:
          [[1400. 1500. 1600.]
           [  nan    0.   nan]
           [1700. 1800.   nan]]
          
          dropna:
          [1400. 1500. 1600. 1700.]
          

          【讨论】:

          • 谢谢你,我认为考虑 n-D 案例非常重要
          【解决方案10】:

          如果有帮助,对于简单的一维数组:

          x = np.array([np.nan, 1, 2, 3, 4])
          
          x[~np.isnan(x)]
          >>> array([1., 2., 3., 4.])
          

          但如果您希望扩展为矩阵并保留形状:

          x = np.array([
              [np.nan, np.nan],
              [np.nan, 0],
              [1, 2],
              [3, 4]
          ])
          
          x[~np.isnan(x).any(axis=1)]
          >>> array([[1., 2.],
                     [3., 4.]])
          

          我在处理 pandas .shift() 功能时遇到了这个问题,由于效率低下,我想不惜一切代价避免使用 .apply(..., axis=1)

          【讨论】:

            【解决方案11】:

            只需填写

             x = numpy.array([
             [0.99929941, 0.84724713, -0.1500044],
             [-0.79709026, numpy.NaN, -0.4406645],
             [-0.3599013, -0.63565744, -0.70251352]])
            
            x[numpy.isnan(x)] = .555
            
            print(x)
            
            # [[ 0.99929941  0.84724713 -0.1500044 ]
            #  [-0.79709026  0.555      -0.4406645 ]
            #  [-0.3599013  -0.63565744 -0.70251352]]
            

            【讨论】:

              【解决方案12】:

              最简单的方法是:

              numpy.nan_to_num(x)
              

              文档:https://docs.scipy.org/doc/numpy/reference/generated/numpy.nan_to_num.html

              【讨论】:

              • 欢迎来到 SO!您提出的解决方案没有解决问题:您的解决方案用大量替换 NaNs,而 OP 要求完全删除元素。
              猜你喜欢
              • 1970-01-01
              • 2020-04-21
              • 2014-06-07
              • 2018-12-21
              • 2019-04-15
              • 2019-12-22
              • 2015-06-08
              • 1970-01-01
              相关资源
              最近更新 更多