值与dtype均一致的DataFrame为何equals返回不等,测试失败?
问题原因分析
1. Test 1 失败原因
表面上两个DataFrame的值和dtype看似一致,但df.equals()返回False的核心原因是元素类型的隐性差异:
- 函数中对
Combo (NPI & Date)列执行了apply(lambda x : x if '<NA>' not in x else np.nan),即使测试数据中没有<NA>值,该列的元素类型会被识别为Union[str, float](因为np.nan是float类型)。 - 测试用例的
output中,Combo (NPI & Date)列的元素是纯字符串类型,pandas的equals()方法会严格检查每个元素的类型,因此返回False。
另外,days_since_dec_30_1899函数通过字符串分割处理Timestamp的方式不可靠,若Timestamp包含时区或特殊格式会直接报错。
2. Test 2 失败原因
当输入NPI为float64类型时:
- 函数中将其转为
Int64(可空整数类型),再转为字符串,此时NPI列的dtype是Nullable String(string类型)。 - 测试用例的
output中NPI列是普通的objectdtype,equals()默认会检查dtype完全一致,因此返回False。
修复方案
方案1:优化日期计算函数(避免字符串分割)
替换不可靠的字符串处理逻辑,直接用Timestamp内置方法获取日期:
def days_since_dec_30_1899(input_date: pd.Timestamp) -> str: delta = input_date.date() - dtm_date(1899, 12, 30) return str(delta.days)
方案2:统一类型转换逻辑,消除dtype差异
修改函数,确保输出的dtype与测试用例一致:
def create_combo_npi_and_date_col(data: pd.DataFrame, date_name: str = 'Date') -> pd.DataFrame: temp = data.copy() days_since_1899 = temp[date_name].apply(days_since_dec_30_1899) # 统一处理NPI类型,保持输出为object dtype if pd.api.types.is_float_dtype(temp['NPI']): temp['NPI'] = temp['NPI'].astype('Int64').astype(str) else: temp['NPI'] = temp['NPI'].astype(str) # 生成Combo列,用replace替换<NA>,避免元素类型混合 temp['Combo (NPI & Date)'] = temp['NPI'] + days_since_1899 temp['Combo (NPI & Date)'] = temp['Combo (NPI & Date)'].replace('<NA>', np.nan) return temp
方案3:调整测试用例(或忽略dtype检查)
如果确认业务逻辑中dtype差异不影响结果,可以在测试时关闭dtype检查:
# Test 1 self.assertTrue(output.equals(create_combo_npi_and_date_col(input), check_dtype=False), 'test 1 has failed') # Test 2 self.assertTrue(output.equals(create_combo_npi_and_date_col(input), check_dtype=False), 'test 2 has failed')
内容的提问来源于stack exchange,提问作者Ryan Folks
相关产品推荐
相关产品推荐

