如何基于两个DataFrame按条件生成结构一致的0/1格式DataFrame
需求说明
基于两个已有的DataFrame df1 和 df2 生成新的DataFrame df3,规则如下:
- 若
df1中对应位置的数值大于等于df2中对应位置的数值,df3对应位置赋值1 - 其余情况赋值0,只要对应位置任意一侧为NaN,统一返回0
示例数据
df1 Date 01K 02K 03K 04K 0 2021-01-01 NaN 3.5 4.2 NaN 1 2021-01-02 2.3 0.1 5.2 2.6 2 2021-01-03 0.3 NaN 2.5 8.2 3 2021-01-04 0.4 NaN 3.0 4.2 df2 Date 01K 02K 03K 04K 0 2021-01-01 NaN NaN NaN NaN 1 2021-01-02 2.5 0.6 5.8 2.3 2 2021-01-03 0.2 NaN 2.5 8.1 3 2021-01-04 0.3 NaN 2.8 4.2 # 预期输出df3 Date 01K 02K 03K 04K 0 2021-01-01 0 0 0 0 1 2021-01-02 0 0 0 1 2 2021-01-03 1 0 1 1 3 2021-01-04 1 0 1 1
可复现测试代码
import pandas as pd import numpy as np df1 = pd.DataFrame({ 'Date':['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04'], '01K':['NaN', 2.3, 0.3, 0.4], '02K':[3.5, 0.1, 'NaN', 'NaN'], '03K':[4.2, 5.2, 2.5, 3.0], '04K':['NaN', 2.6, 8.2, 4.2]}) df1 = df1.replace('NaN',np.nan) df2 = pd.DataFrame({ 'Date':['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04'], '01K':['NaN', 2.5, 0.2, 0.3], '02K':['NaN', 0.6, 'NaN', 'NaN'], '03K':['NaN', 5.8, 2.5, 2.8], '04K':['NaN', 2.3, 8.1, 4.2]}) df2 = df2.replace('NaN',np.nan)
现有问题
使用np.where(df1>=df2, 1, 0)只能得到numpy数组,无法保留原DataFrame的行列结构,需要适合大数据集的高效实现方案。
解决方案
直接使用pandas原生向量化操作即可,底层为C实现,大数据集下性能优异,且能完全保留原DataFrame的行列结构:
# 复制保留Date列 df3 = df1[['Date']].copy() # 提取所有数值列 num_cols = df1.columns.drop('Date') # 向量化比较后将NaN填充为False,转整数得到0/1值 df3[num_cols] = (df1[num_cols] >= df2[num_cols]).fillna(False).astype(int)
方案说明
df1[num_cols] >= df2[num_cols]会返回对应位置的布尔值,存在NaN的位置返回NaN.fillna(False)将所有NaN(即任意一侧对应位置为NaN)统一替换为False.astype(int)将布尔值转为整数,True对应1,False对应0,完全符合需求- 最终生成的df3列名、行索引和df1完全一致,无需额外处理结构
内容的提问来源于stack exchange,提问作者fjurt
相关产品推荐
相关产品推荐

