【科研数据处理】DataFrame中标记空值为0,非空值为1

这篇博客介绍了在数据处理中如何使用Pandas DataFrame将空值标记为0,非空值标记为1的方法。通过先填充空值,再替换或者直接利用字符串转化和条件判断来实现这一目标。无论是处理时间类型还是非时间类型的数据,都能找到简单有效的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DataFrame中标记空值为0,非空值为1


手动反爬虫,禁止转载: 原博地址 https://blog.youkuaiyun.com/lys_828/article/details/117820052

 知识梳理不易,请尊重劳动成果,文章仅发布在优快云网站上,在其他网站看到该博文均属于未经作者授权的恶意爬取信息

测试数据如下,可以自己指定,由于在数据处理过程中遇到了需要进行非空的处理

在这里插入图片描述
处理的思路是较为简单的,可以先填充然后在针对非填充的数值再进行替换,需要使用到fillna()的方法,然后就是apply()函数的使用了
在这里插入图片描述
同理对于非时间的转化也是一致
在这里插入图片描述
还有一种方式,我自己较为常用的,就是如论如何都可以对单元进行字符串转化,最后空值也会有字符串的表现形式,然后判断如果不等于这个形式就标记为1,是这个形式就标记为0,比如时间

""" 第一步读取数据,取出我们想要的指标 服务器地址:localhost 数据库:bdpd_rmv 账户名:root 密码:123456 端口:3306 字符编码:'utf8mb4' 表名:RMV_KDSQ_MODEL_INDEX_INFO 提取指定字段:SCORE,BAD_FLAG """ import pandas as pd from sqlalchemy import create_engine import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.font_manager as fm import numpy as np def calKs(): # 数据库连接配置 db_config = { 'host': 'localhost', # 服务器地址 'port': 3306, # 端口 'user': 'root', # 账户名 'password': '123456', # 密码 'database': 'bdpd_rmv', # 数据库名 'charset': 'utf8mb4' # 字符编码(默认使用utf8mb4) } # 步骤1: 创建数据库连接 # 使用SQLAlchemy创建MySQL连接引擎 # 格式: mysql+pymysql://用户名:密码@主机:端口/数据库名 engine = create_engine( f"mysql+pymysql://{db_config['user']}:{db_config['password']}@{db_config['host']}:{db_config['port']}/{db_config['database']}?charset={db_config['charset']}" ) # 步骤2: 读取数据并提取指定字段 query = "SELECT * FROM RMV_KDSQ_MODEL_INDEX_INFO" # SQL查询语句,获取所有列 data = pd.read_sql(query, engine) # 执行查询并读取到DataFrame # 将列名转换为大写(确保字段名一致性) data.columns = data.columns.str.upper() # 检查数据 print(f"成功读取 {len(data)} 条记录") print(data.head()) # 打印前5行数据(用于调试) # 修复步骤1: 确保所有列使用正确数据类型 # 将SCORE转换为浮点数(无法转换的设为NaN) data['SCORE'] = pd.to_numeric(data['SCORE'], errors='coerce') # 将BAD_FLAG转换为整数(0/1) # 处理数值数据:无法转换的设为NaN,然后用0填充,最后转换为整数 data['BAD_FLAG'] = pd.to_numeric(data['BAD_FLAG'], errors='coerce').fillna(0).astype(int) # 定义一个新的分组,按照FLAG和MONITOR_DT做分组 cols = ['FLAG', 'MONITOR_DT'] # 分组依据的列 # 按FLAG和MONITOR_DT分组,取每组第一条记录(实际只需要分组标识) modelInfo = data[cols].groupby(by=cols).first().reset_index() # 获取分组标识列表 flag_list = modelInfo['FLAG'].to_list() monitor_list = modelInfo['MONITOR_DT'].to_list() print(flag_list, monitor_list) # 打印分组标识(调试用) # 获取分组数量 modelInfo_len = len(flag_list) # 遍历每个分组 for i in range(modelInfo_len): print(flag_list[i], monitor_list[i]) # 打印当前分组信息 # 筛选当前分组的数据(三种方法) # 方法1: 使用where(不推荐,会保留所有行,不符合条件的设为NaN) # df = data.where((data['FLAG'] == flag_list[i]) & (data['MONITOR_DT'] == monitor_list[i])) # 方法2: 布尔索引(推荐) # df = data[(data['FLAG'] == flag_list[i]) & (data['MONITOR_DT'] == monitor_list[i])] # 方法3: 使用query(当前代码使用的方法) # 注意:字符类型的值需要加引号,但这里flag_list[i]可能是数值类型,可能导致错误 df = data.query(f"FLAG == '{flag_list[i]}' and MONITOR_DT == '{monitor_list[i]}'") # 选择需要的列(SCORE和BAD_FLAG) df = df[['SCORE', 'BAD_FLAG']] # 步骤2: 按SCORE升序排序(排序后重置索引) df.sort_values('SCORE', ascending=True, inplace=True) df.reset_index(drop=True, inplace=True) # 重置索引,丢弃原索引 # 添加行号(从1开始) df['row_number'] = range(1, len(df) + 1) # 步骤3: 计算基本统计量 total_samples = len(df) # 总样本数 total_bad = df['BAD_FLAG'].sum() # 坏样本总数 total_good = total_samples - total_bad # 好样本总数 # 步骤4: 计算累计值 df['cum_bad'] = df['BAD_FLAG'].cumsum() # 累计坏样本数 df['GOOD_FLAG'] = 1 - df['BAD_FLAG'] # 创建好样本标志(1-BAD_FLAG) df['cum_good'] = df['GOOD_FLAG'].cumsum() # 累计好样本数 # 计算累计占比(避免除零错误) df['cum_bad_pct'] = df['cum_bad'] / total_bad if total_bad > 0 else 0 df['cum_good_pct'] = df['cum_good'] / total_good if total_good > 0 else 0 # 步骤5: 计算KS值(好坏占比差值的最大绝对值) df['cum_diff'] = abs(df['cum_bad_pct'] - df['cum_good_pct']) # 计算每个点的差值 # 找到最大差值(即KS值) ks_value = df['cum_diff'].max() # 找到KS值对应的分数点(使用idxmax获取最大差值的索引) print(i, '找到KS值对应的分数点:', df['cum_diff'].idxmax()) # ks_point = df.loc[df['cum_diff'].idxmax(), 'SCORE'] # ks_point=df.query(f'cum_diff=={ks_value}')['row_number'].to_list()[0] ks_point=np.argmax(df['cum_diff'])+1 # 输出结果 print(f"\nKS值计算结果:") print(f"最大KS值: {ks_value:.4f}") print(f"KS值对应的分数点: {ks_point}") print(df) # 绘图(传入当前分组的相关数据) ks_plot(ks=ks_value, x=df['row_number'], y1=df['cum_bad_pct'], y2=df['cum_good_pct'], ks_point=ks_point, num=i) def ks_plot(ks, x, y1, y2, ks_point, num): """绘制KS曲线图""" # 设置中文字体支持 plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'KaiTi', 'SimSun'] # 常用中文字体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 # 创建图形 plt.figure(figsize=(10, 6)) # 绘制两条曲线 plt.plot(x, y1, label='累计坏客户占比') # 坏客户累计占比曲线 plt.plot(x, y2, label='累计好客户占比') # 好客户累计占比曲线 # 注释:当前代码中KS点标记被注释掉了 plt.axvline(x=ks_point, color='r', linestyle='--', label=f'KS点(row_number={ks_point})') # 设置图表标题和标签 plt.title(f'KS曲线 (KS值={ks:.4f})') plt.xlabel('样本数') # x轴标签 plt.ylabel('累计占比') # y轴标签 # 添加图例和网格 plt.legend() plt.grid(True) # 保存和显示图像 # plt.savefig(f'ks_{num}.png') # 保存为图片(文件名包含分组编号) plt.show() # 展示图片 if __name__ == '__main__': # 程序入口 calKs() 给我逐行注释
最新发布
07-24
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lys_828

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值