为何np.where会将部分pandas数据转换为NaN值?
问题描述
我需要拆分某列中包含\n的数据值,已将该列转为object类型,原始数据片段如下:
0 881567905 1 881046000 2 881046025 3 882935053 4 881006805 5 882130610 6 882036810 7 882428300 8 882428400 9 884343355\n183055900
使用\n拆分数据后,通过np.where()函数在生成多元素列表的位置保留列表,否则返回单个元素,但处理后部分数据被替换为NaN值,处理后的数据片段如下:
0 881567905 1 881046000 2 881046025 3 NaN 4 NaN 5 NaN 6 NaN 7 882428300 8 882428400 9 [884343355, 183055900]
未被转换的数据与被转换的数据在长度、类型或结构上无明显差异。拆分替换代码为:
file_no = df['file_no'].str.split("\n") df['file_no'] = np.where(file_no.str.len()==1,file_no.str[0],file_no)
预处理代码为:
path = r'Z:\clients.xlsx' df = pd.read_excel(path,sheet_name="Master List",header=0,engine="openpyxl") df = df.rename(columns={'Our File #':'file_no', 'ID #':'ID'}) df = df.astype({'file_no':'object'}) df = df[df.file_no.notnull()]
请问为何这些pandas值会被NaN替换?
原因分析与解决方案
核心原因
问题出在np.where()的类型兼容性限制:
file_no.str[0]返回的是字符串类型的Series,而file_no本身是列表类型的Seriesnp.where()会强制统一输出类型,当两种类型无法兼容转换时,对应位置的值会被转为NaN
另外,虽然你将列转为object类型,但read_excel可能仍对部分数值型数据保留了底层数值类型存储,导致str.split()对这些元素返回NaN,后续str.len()也会得到NaN,使得np.where()的条件判断不成立,进一步触发类型不兼容问题。
可行解决方案
方案1:使用apply方法直接处理(推荐)
通过apply()针对每个元素做判断,避免类型统一冲突:
df['file_no'] = df['file_no'].apply(lambda x: x.split('\n') if '\n' in str(x) else x)
如果需要更严谨处理非字符串元素:
def split_file_no(x): s = str(x) parts = s.split('\n') return parts if len(parts) > 1 else s df['file_no'] = df['file_no'].apply(split_file_no)
方案2:修正原代码的类型一致性
如果允许单个元素也以列表形式存在,可以统一类型:
file_no = df['file_no'].str.split("\n") df['file_no'] = file_no.apply(lambda x: x if len(x) > 1 else x[0])
内容的提问来源于stack exchange,提问作者Jeff Gordon
相关产品推荐
相关产品推荐

