基于已有DataFrame列条件生成新DataFrame为空的bug排查求助
问题概述
生成两个DataFrame,第二个通过对第一个的某一列设置RH == 10的条件筛选创建。第一个DataFrame生成成功(包含885482行),且文本文件中确实存在符合条件的行,但第二个DataFrame为空。当循环步长设为0.5时代码可正常工作,但步长改为0.1时出现问题。
原代码
import numpy as np import pandas as pd import os # 工作目录路径 wdir = r'C:\Users\abdul\Documents\Research\CdTe\a-SiC_H and a-SiC_B_H on CdTe' os.chdir(wdir) full_data_file = open('Z_data_full_data.txt', 'w') Selected_rows_data_file = open('Z_data_selected_data.txt', 'w') H2 = 100.00 # sccm 固定值 # 初始化存储数据的列表 CH4_lst = [] SiH4_lst = [] H2_lst = [] Z_lst = [] RH_lst = [] # 嵌套循环生成数据 CH4 = 1 # sccm while CH4 <= 95: SiH4 = 1 # sccm while SiH4 <= 95: Z_ratio = CH4 / (SiH4 + CH4) RH = H2 / (CH4 + SiH4) CH4_lst.append(CH4) SiH4_lst.append(SiH4) H2_lst.append(H2) Z_lst.append(Z_ratio) RH_lst.append(RH) # 内循环步长 SiH4 += 0.10 # 外循环步长 CH4 += 0.10 # 生成完整数据的DataFrame df_1 = pd.DataFrame(list(zip(CH4_lst, SiH4_lst, H2_lst, RH_lst, Z_lst)), columns = ['CH4_flowrate(sccm)', 'SiH4_flowrate(sccm)', 'H2_flowrate(sccm)', 'RH=[H2]/([CH4]+[SiH4])', 'Z=CH4/([CH4]+[SiH4])']) # 筛选符合条件的行生成第二个DataFrame selecting_rows = df_1['RH=[H2]/([CH4]+[SiH4])'].values == 10 df_2 = pd.DataFrame(df_1[selecting_rows]) # 写入文件 full_data_file.write(df_1.to_string(justify='right', index=False)) Selected_rows_data_file.write(df_2.to_string(justify='right', index=False)) full_data_file.close() Selected_rows_data_file.close() os.startfile('{}\\Z_data_full_data.txt'.format(wdir), 'open') os.startfile('{}\\Z_data_selected_data.txt'.format(wdir), 'open')
问题根源:浮点数精度误差
0.1在二进制中是无限循环小数,累加时会产生精度偏移。例如,当CH4 + SiH4理论值应为10时,实际计算结果可能是9.999999999999998或10.000000000000002,直接用==10无法匹配这些近似值。而步长设为0.5时,0.5是二进制可精确表示的数,累加后CH4 + SiH4的结果是精确的10,因此筛选条件生效。
解决方案
方案1:使用近似比较替代精确相等
将筛选条件改为判断值是否在10的极小误差范围内:
# 替换原筛选代码 tolerance = 1e-9 # 可根据需求调整精度 selecting_rows = np.abs(df_1['RH=[H2]/([CH4]+[SiH4])'] - 10) < tolerance df_2 = df_1[selecting_rows].copy()
方案2:用整数计算避免浮点数误差
将循环变量改为整数(代表0.1的倍数),最后再转换为实际数值:
# 修改循环部分 CH4_int = 10 # 对应1.0 sccm while CH4_int <= 950: # 对应95.0 sccm SiH4_int = 10 # 对应1.0 sccm while SiH4_int <= 950: CH4 = CH4_int / 10 SiH4 = SiH4_int / 10 Z_ratio = CH4 / (SiH4 + CH4) RH = H2 / (CH4 + SiH4) CH4_lst.append(CH4) SiH4_lst.append(SiH4) H2_lst.append(H2) Z_lst.append(Z_ratio) RH_lst.append(RH) SiH4_int += 1 # 步长1对应0.1 sccm CH4_int += 1
这种方式能保证CH4 + SiH4的计算结果精确,筛选条件==10可正常生效。
方案3:使用numpy的isclose函数
利用numpy的isclose函数进行近似匹配:
# 替换原筛选代码 selecting_rows = np.isclose(df_1['RH=[H2]/([CH4]+[SiH4])'], 10) df_2 = df_1[selecting_rows].copy()
内容的提问来源于stack exchange,提问作者abdulquader
相关产品推荐
相关产品推荐

