为何np.nan在Pandas字符串列未正常转换?如何生成替代缺失值?
问题与解答
问题描述
使用以下代码生成含缺失值的数据集:
import pandas as pd import numpy as np n = 20 df = pd.DataFrame({"x": np.random.choice(["dog","cat",np.nan],n), "y": range(0,n)})
随后执行pd.notnull(df["x"])检查缺失值时,未检测到任何缺失值——排查发现代码中的np.nan被转换成了字符串"nan",而非Pandas可识别的缺失值。但将np.nan替换为None,用np.random.choice(["dog","cat",None],n)创建数据时,就能正常检测到缺失值。
需解答:
- 为何
np.nan未被正确识别为缺失值,反而转为字符串? - 如何不使用
np.nan或None,为字符串列生成随机缺失值?
解答
1. np.nan转为字符串"nan"的原因
np.random.choice要求输入的数组元素类型统一。当传入的列表混合了字符串("dog"、"cat")与浮点类型的np.nan时,NumPy会自动将所有元素转换为字符串类型——这是因为字符串是能兼容所有元素的通用类型。此时np.nan被转为它的字符串表示"nan",并非Pandas认可的缺失值标记。
而传入None时,NumPy会将数组类型设为object,None进入Pandas后会自动转换为pd.NA(旧版本为np.nan),也就是真正的缺失值,因此能被pd.notnull正常检测。
2. 不使用np.nan/None生成随机缺失值的方法
方法一:先生成纯字符串数组,再随机替换为pd.NA
import pandas as pd import numpy as np n = 20 # 生成仅包含"dog"和"cat"的随机数组 x = np.random.choice(["dog", "cat"], n) # 随机选择部分位置(示例为10%比例)替换为pd.NA mask = np.random.choice([True, False], n, p=[0.1, 0.9]) x[mask] = pd.NA # 创建DataFrame df = pd.DataFrame({"x": x, "y": range(n)})
生成的缺失值是Pandas原生支持的pd.NA,可被pd.notnull、pd.isnull正确识别。
方法二:用列表推导式直接生成
import pandas as pd import numpy as np n = 20 choices = ["dog", "cat", pd.NA] # 按自定义概率随机选择(示例给pd.NA分配20%概率) x = [np.random.choice(choices, p=[0.4, 0.4, 0.2]) for _ in range(n)] df = pd.DataFrame({"x": x, "y": range(n)})
利用Python列表的灵活性,避免NumPy自动类型转换问题,直接生成包含pd.NA的列表,传入DataFrame后即为正确的缺失值。
内容的提问来源于stack exchange,提问作者P.Jo
相关产品推荐
相关产品推荐

