【问题标题】:Is there a Numpy or Pandas setting to issue a warning whenever a NaN value is created是否有 Numpy 或 Pandas 设置在创建 NaN 值时发出警告
【发布时间】:2018-01-01 12:54:19
【问题描述】:

我花了很多时间与 Pandas 打交道,它使用 numpy 数组来存储数字。

在我的用例中,不应该有任何 NaN 值 - 它们表明出现了问题(通常是与 Pandas 相关的错误,例如错误连接的数据框、错误加载的数据等)

如果 Pandas 或 Numpy 有一个设置,如果 NaN 值出现在数据框中的任何系列中,会立即发出警告,这将很有帮助。 (这个问题不是关于 NaN 替换或插补。只是警告。)

是的,可以在每个阶段编写大量本地检查(do this thing. Now check whether you created NaNs. Do this other thing. Check again whether you created NaNs 等),但这非常冗长且效率低下。我想告诉 pandas 的是 if you ever put a NaN value in a dataframe, immediately issue a warning - 一次,作为我的 jupyter notebook 顶部的全局设置。

有谁知道这样做的全局设置是否存在?

【问题讨论】:

  • 为什么要在存在 NaN 时发出警告,您是否正在寻找一种方法来删除包含 NaN 的行或覆盖其内容?如果是,请在下面查看我的答案。如果没有,请提供更多详细信息。
  • @MedAli 我想在存在 NaN 时发出警告。我会澄清这个问题。
  • 我没有答案,但可以评论其他各种语言如何做到这一点。如果您有编译语言(例如 Fortran 或 C),您可以使用编译时标志对其进行一般控制。更高级别的程序(SAS 或 Stata)通常像 pandas 一样处理这个问题,并默默地创建缺失值。我认为用户将不得不负责检查这里的计算结果。意外创建 NaN 只是成千上万可能出错的事情之一,现代语言的总体方法是提供用于数据验证的工具,而不是导致运行时崩溃。
  • @JohnE " 而不是导致运行时崩溃。" - 我不想引发异常,我只想显示一个漂亮的红色警告框。

标签: python pandas numpy nan


【解决方案1】:

如果您只是想发出警告,您可以使用df.isnull().values.any() 检查您的数据框是否包含任何NaN,您可以使用warnings 模块发出警告。

这是一个工作示例:

>>> from StringIO import StringIO 
>>> import pandas as pd 
>>> st = """ 
... col1|col2
... 1|
... 2|3 
... """
>>> df = pd.read_csv(StringIO(st),sep="|") 
>>> df.head() 
   col1  col2
0     1   NaN
1     2     3
>>> import warnings                              ^
>>> if df.isnull().values.any(): 
...     warnings.warn("there is NaN")
... 
__main__:2: UserWarning: there is NaN
>>> 

如果您正在寻找 pandas 中的一般设置,基于源代码 here,检查 DataFrame class 所做的构造数据帧不包括在存在 NaN 时发出警告的方法。因此,必须更新核心 pandas 以添加它。这是 DataFrame 类完成的完整检查的摘录。

def __init__(self, data=None, index=None, columns=None, dtype=None,
             copy=False):
    if data is None:
        data = {}
    if dtype is not None:
        dtype = self._validate_dtype(dtype)

    if isinstance(data, DataFrame):
        data = data._data

    if isinstance(data, BlockManager):
        mgr = self._init_mgr(data, axes=dict(index=index, columns=columns),
                             dtype=dtype, copy=copy)
    elif isinstance(data, dict):
        mgr = self._init_dict(data, index, columns, dtype=dtype)
    elif isinstance(data, ma.MaskedArray):
        import numpy.ma.mrecords as mrecords
        # masked recarray
        if isinstance(data, mrecords.MaskedRecords):
            mgr = _masked_rec_array_to_mgr(data, index, columns, dtype,
                                           copy)

        # a masked array
        else:
            mask = ma.getmaskarray(data)
            if mask.any():
                data, fill_value = maybe_upcast(data, copy=True)
                data[mask] = fill_value
            else:
                data = data.copy()
            mgr = self._init_ndarray(data, index, columns, dtype=dtype,
                                     copy=copy)

    elif isinstance(data, (np.ndarray, Series, Index)):
        if data.dtype.names:
            data_columns = list(data.dtype.names)
            data = dict((k, data[k]) for k in data_columns)
            if columns is None:
                columns = data_columns
            mgr = self._init_dict(data, index, columns, dtype=dtype)
        elif getattr(data, 'name', None) is not None:
            mgr = self._init_dict({data.name: data}, index, columns,
                                  dtype=dtype)
        else:
            mgr = self._init_ndarray(data, index, columns, dtype=dtype,
                                     copy=copy)
    elif isinstance(data, (list, types.GeneratorType)):
        if isinstance(data, types.GeneratorType):
            data = list(data)
        if len(data) > 0:
            if is_list_like(data[0]) and getattr(data[0], 'ndim', 1) == 1:
                if is_named_tuple(data[0]) and columns is None:
                    columns = data[0]._fields
                arrays, columns = _to_arrays(data, columns, dtype=dtype)
                columns = _ensure_index(columns)

                # set the index
                if index is None:
                    if isinstance(data[0], Series):
                        index = _get_names_from_index(data)
                    elif isinstance(data[0], Categorical):
                        index = _default_index(len(data[0]))
                    else:
                        index = _default_index(len(data))

                mgr = _arrays_to_mgr(arrays, columns, index, columns,
                                     dtype=dtype)
            else:
                mgr = self._init_ndarray(data, index, columns, dtype=dtype,
                                         copy=copy)
        else:
            mgr = self._init_dict({}, index, columns, dtype=dtype)
    elif isinstance(data, collections.Iterator):
        raise TypeError("data argument can't be an iterator")
    else:
        try:
            arr = np.array(data, dtype=dtype, copy=copy)
        except (ValueError, TypeError) as e:
            exc = TypeError('DataFrame constructor called with '
                            'incompatible data and dtype: %s' % e)
            raise_with_traceback(exc)

        if arr.ndim == 0 and index is not None and columns is not None:
            if isinstance(data, compat.string_types) and dtype is None:
                dtype = np.object_
            if dtype is None:
                dtype, data = infer_dtype_from_scalar(data)

            values = np.empty((len(index), len(columns)), dtype=dtype)
            values.fill(data)
            mgr = self._init_ndarray(values, index, columns, dtype=dtype,
                                     copy=False)
        else:
            raise ValueError('DataFrame constructor not properly called!')

    NDFrame.__init__(self, mgr, fastpath=True)

因此,您需要提交功能请求才能将其添加到 pandas。

【讨论】:

  • 我觉得这不是 Roko Mijic 所要求的。我认为他宁愿寻找像著名的SettingWithCopyWarning 这样的东西。但是,我不确定这是否实施。可以考虑编写一个装饰器来在操作后执行检查并修补经常使用的 pandas 函数。如果我错了,请纠正我。
  • @Quickbeam2k1 问题不清楚。所以我尽可能多地提示并要求在 cmets 中进行澄清。
  • @Quickbeam2k1 完全正确。如果有 NaN,我不想重复告诉 Pandas 警告我。
  • @MedAli 感谢您的回答,但正如问题中所述,我正在寻找一种方法将其实现为全局设置,告诉 numpy/pandas 在每次操作后检查数据框中的 NaN。
  • 感谢编辑。也许非常了解 Pandas 的人应该为此功能提交拉取请求。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-31
  • 2016-05-19
  • 1970-01-01
  • 2011-05-03
  • 2017-09-18
相关资源
最近更新 更多