【问题标题】:Replace empty values of a dictionary with NaN用 NaN 替换字典的空值
【发布时间】:2018-03-11 21:40:20
【问题描述】:

我有一个缺少值的字典(键在那里,但关联的值是空的)。例如我想要下面的字典:

dct = {'ID':'', 'gender':'male', 'age':'20', 'weight':'', 'height':'5.7'}

改成这种形式:

dct = {'ID':NaN, 'gender':'male', 'age':'20', 'weight':NaN, 'height':'5.7'}

我怎样才能以最省时的方式编写它?

【问题讨论】:

  • 尽量避免以掩盖其他名称的方式命名变量。即不要将您的变量命名为dict,因为这会影响内置类型名称dict
  • @ndmeiri 好点!谢谢!
  • 为什么指定“最省时的方式”?如果就地更新dct 确实比构建新的dct 快几纳秒,反之亦然,即使它更难阅读或不阅读,您是否会选择更快的?与其他代码一起玩吗?如果对于一些大型 dicts 来说更快的东西对于一堆小的 dicts 来说更慢怎么办?
  • None 可能比NaN 更合适,尤其是因为您没有将值存储为float
  • @chepner:实际上,因为他所有的其他值都是字符串,即使是那些明显打算是整数 (age) 和浮点数 (height) 的值,只是 '',或者也许像'N/A' 这样的特殊字符串可能会更好……

标签: python dictionary missing-data


【解决方案1】:

您可以使用字典理解。此外,正如 cmets 中所述,在 Python 中命名 dict 并不是一个好习惯。:

dct = {'ID':'', 'gender':'male', 'age':'20', 'weight':'', 'height':'5.7'}
dct = {k: None if not v else v for k, v in dct.items() }
print(dct)

输出:

{'ID': None, 'gender': 'male', 'age': '20', 'weight': None, 'height': '5.7'}

只需将None 替换为您想要的默认值即可。

在您的问题中,您想替换为NaN

您可以使用以下任何一种:

float('nan') 如果您使用的是 Python 2.x 或 Python

math.nan 用于 Python 3.5+

numpy.nan 使用 numpy

【讨论】:

  • 是的,这就是我要找的。但是当我用 NaN 替换 None 时,我得到了这个错误:“NameError: name 'NaN' is not defined”
  • 如果你想使用 NaN 你应该看看 numpy.你会想使用numpy.nan
  • NaN 不需要 numpy;它内置为math.nan。或者,如果您使用的是早期版本的 Python,float('nan') 将可以追溯到早期的 2.x 天。如果你实际上没有使用 numpy,你可能不想要它的nan——它不能像内置的那样很好地使用普通的 Python 浮点数。
  • 值得注意的是,这将替换所有“假”值,因此它将按预期在空字符串上工作,但如果某些字典值实际上是 None0False 或一些其他这样的值,它可能没有预期的效果。
  • 请注意,这实际上并不是最省时的解决方案。对于大多数用例来说,就地改变字典(即使这意味着使用稍慢的for 语句而不是理解)几乎肯定会更快。并且为任一版本编写一个使用 fast-dict-iter API 的 C 扩展将会更快。我怀疑这种权衡在这种情况下是否值得,但他确实说过“最省时的方式”,所以可能值得评论说这不是最省时的方式,但可能是他应该做的无论如何都要做。
【解决方案2】:

您可以使用带有布尔or 表达式的隐式语法:

In [1]: dct = {'ID':'', 'gender':'male', 'age':'20', 'weight':'', 'height':'5.7'}

In [2]: {k: v or None for k, v in dct.items()}
Out[2]: {'ID': None, 'age': '20', 'gender': 'male', 'height': '5.7', 'weight': None}

但请注意,The Zen of Python 中说:

显式优于隐式。

【讨论】:

    【解决方案3】:

    你可以创建一个类对象来表示NaN

    class NaN:
      def __init__(self, default=None):
        self.val = default
      def __repr__(self):
        return 'NaN'
    
    dct = {'ID':'', 'gender':'male', 'age':'20', 'weight':'', 'height':'5.7'}
    new_d = {a:NaN() if not b else b for a, b in dct.items()}
    

    输出:

    {'gender': 'male', 'age': '20', 'ID': NaN, 'weight': NaN, 'height': '5.7'}
    

    【讨论】:

      【解决方案4】:

      您可以使用 for 循环遍历字典中的所有键和值。

      dct = {'ID': '', 'gender': 'male', 'age': '20', 'weight': '', 'height': '5.7'}
      
      
      for key, value in dct.items():
            if value == '':
                 dct[key] = 'NaN'
      print(dct)
      
      1. 您使用一系列键值对创建了字典。
      2. 我使用了 for 循环和 .items() 方法来遍历字典中的每个键值对。
      3. 如果键/值对的值为空字符串,我们将该特定值更改为“NaN”,其余保持不变。
      4. 当我们打印新字典时,我们得到这个输出:

        {'ID': 'NaN', 'gender': 'male', 'age': '20', 'weight': 'NaN', 'height': '5.7'}
        

      这很节省时间,因为它是一个快速循环,只要您可以接受不是“NaN”值是字符串。我不确定您是否正在寻找它们作为字符串,但是,如果您正在寻找它,您可以非常简单地将值从“NaN”更改为 None。 for 循环在时间方面相对有效,因为它将快速迭代每个值。

      【讨论】:

      • 如果我记得 math.nan 如果你导入 math 模块会给你:nan。如果您希望它按照原始代码的方式格式化,您可以使用字符串“NaN”。如果你想要诸如 None 之类的东西,你可以将 value = 设置为 None。我假设其中一个选项对您有用。
      猜你喜欢
      • 2022-01-05
      • 2022-12-06
      • 2017-09-08
      • 2020-12-25
      • 1970-01-01
      • 1970-01-01
      • 2015-01-06
      • 2019-09-29
      • 1970-01-01
      相关资源
      最近更新 更多