用NaN替换字典中的空值

10

我有一个字典,其中一些值是缺失的(键存在,但关联的值为空)。例如,我想要下面这个字典:

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
1
@ndmeiri 很好的观点!谢谢! - user9439906
1
你为什么要指定“最省时的方式”?如果实际上就算是更新dct比构建新的dct快几个纳秒,或者反之亦然,你会选择更快的那一个,即使它更难读懂或者与你代码的其他部分不太协调吗?如果对于一些大型字典来说更快的方法对于一堆小型字典来说却更慢呢? - abarnert
2
使用None可能比NaN更合适,特别是因为您没有将该值存储为float - chepner
@chepner:实际上,由于他的所有其他值都是字符串,即使是明显意图为整数(age)和浮点数(height)的值,只使用''或者一些特殊字符串如'N/A'可能会更好... - abarnert
4个回答

20

你可以使用字典推导式。同时,正如评论中所指出的那样,在Python中将某些变量命名为dict不是一个好的做法。

你可以使用字典推导式。同时,正如评论中所指出的那样,在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 <3.5

math.nan 适用于 Python 3.5+

numpy.nan 使用 numpy


如果你想使用 NaN,你应该研究一下 numpy。你需要使用 numpy.nan - user3483203
@user9439906 更新了我的答案,展示了如何使用 numpy 的 NaN。 - user3483203
1
你不需要使用numpy来处理NaN,因为它已经集成在math.nan中了。如果你使用的是早期版本的Python,那么float('nan')也可以在2.x版本中使用。如果你实际上没有使用numpy,那么你可能不需要它的nan——它与普通的Python浮点数的兼容性不如内置的nan - abarnert
2
值得注意的是,这将替换所有“falsey”值,因此对于空字符串,它将按预期工作。但是,如果某些字典值实际上是None0False或其他类似的值,则可能不会产生所需的效果。 - trent
1
请注意,这并不是最高效的解决方案。直接在原地突变字典(尽管这意味着使用稍微慢一些的for语句而不是理解)几乎肯定会更快地满足大多数用例。编写一个使用快速字典迭代器 API 的 C 扩展程序将更加快速。我对这种情况下权衡利弊的看法甚至远非值得一提,但他确实说过“最高效的方式”,因此或许有必要发表评论,说明这不是最高效的方式,但这可能是他应该采取的措施。 - abarnert
显示剩余3条评论

1

您可以在布尔表达式中使用隐式语法 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}

但请注意,在Python禅宗中有这样一句话:

显式优于隐式。


0
您可以创建一个类对象来表示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'}

0
你可以使用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。对于循环而言,它在时间上相对高效,因为它会快速迭代每个值。


如果我回忆起 math.nan,如果你导入 math 模块,将会得到:nan。如果你想按照原始代码的格式进行格式化,可以使用字符串 'NaN'。如果你想要像 None 这样的东西,你可以将值设置为 None。我假设其中一个选项适合你。 - Simeon Ikudabo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接