在使用数据过程中,我们常常会遇到NULL值,对于NULL的存在,你们是否在乎呢?
常见的场景:使用Excel进行合并单元格的数据时,将他们录入数据库或者加载到PowerBI,合并单元格的数据只显示一行有数据,其它则显示NULL,这种情况需要对数据空值进行填充,才能真正用于可视化和报表开发;
实际场景:有这样一份关于企业用户数的每天记录,但由于系统原因常常出现有些天企业用户数没有进行统计,测试数据如下:
create table wechat
(
date1 date,
num int);
insert into wechat values ('2022-07-01', 5),
('2022-07-02', 6),
('2022-07-03', null),
('2022-07-04', 7),
('2022-07-05', null),
('2022-07-06', null),
('2022-07-07', 8),
('2022-07-08', null),
('2022-07-09', null),
('2022-07-10', null),
('2022-07-11', 9);
针对于这些没有统计的日期,进行补0不太正常,企业用户数也不太可能一下子减为0,所以客户希望可以根据最近一天的用户数进行填充。
需求分析:客户希望根据最近一天的用户数进行填充NULL值,那么这样的话就有两种情况,根据前一天向下填充用户数和后一天向上填充用户数,我们知道Power Query在功能栏上可以直接点击实现,那如何在SQL和Python中进行实现呢?
count(字段):统计不为NULL的记录数;
在这里小编巧妙的运用了count(column) 和开窗函数结合,这样就计算出了累计不为NULL的记录数,然后根据记录数进行分组,取组内最大值进行填充,这样便解决了问题;
由于Mysql窗口函数不太支持添加 ignore nulls ,这里采用了子查询方式处理,如果有需要小编也可以准备一份Oracle的处理方式哦!
select date1,
num,
max(num) over (partition by a) num_next, -- 向下填充
max(num) over (partition by b) num_up -- 向上填充
from (select date1,
num,
count(num) over w1 a, -- 向下累计不为null的记录数
count(num) over w2 b -- 向上累计不为null的记录数
from wechat
window w1 as (order by date1),
w2 as (order by date1 desc)) t
order by date1;
data1 | num | num_next | num_up |
---|---|---|---|
2022-07-01 | 5 | 5 | 5 |
2022-07-02 | 6 | 6 | 6 |
2022-07-03 | 6 | 7 | |
2022-07-04 | 7 | 7 | 7 |
2022-07-05 | 7 | 8 | |
2022-07-06 | 7 | 8 | |
2022-07-07 | 8 | 8 | 8 |
2022-07-08 | 8 | 9 | |
2022-07-09 | 8 | 9 | |
2022-07-10 | 8 | 9 | |
2022-07-11 | 9 | 9 | 9 |
对于空值的处理Python有专门的fillna函数处理,有兴趣的同学可以去官网进行查阅:fillna语法
在这里我们进行了简单的使用:
# 导入所需要的模块
import pandas as pd
from sqlalchemy import create_engine
# 与本地数据库建立连接
engine = create_engine(str(r'mysql+pymysql://%s:' '%s' '@%s/%s' '?charset=UTF8MB4')%('root', '1q2w3e4r', '127.0.0.1', 'test'))
# 获取测试数据
sql1 = " select * from wechat "
data1 = pd.read_sql_query(sql1,engine)
### 以上是测试数据在Mysql数据库中的获取方法,也可直接读取CSV文件如下 ###
# 直接读取CSV文件测试数据
data1 = pd.read_csv('/Users/guanfawang/Desktop/test.csv')
# 向下填充
data1.insert(loc=2,column='num_next',value=data1['num'].fillna(method='ffill'))
# 向上填充
data1.insert(loc=3,column='num_up',value=data1['num'].fillna(method='bfill'))
data1
data1 | num | num_next | num_up |
---|---|---|---|
2022-07-01 | 5 | 5 | 5 |
2022-07-02 | 6 | 6 | 6 |
2022-07-03 | 6 | 7 | |
2022-07-04 | 7 | 7 | 7 |
2022-07-05 | 7 | 8 | |
2022-07-06 | 7 | 8 | |
2022-07-07 | 8 | 8 | 8 |
2022-07-08 | 8 | 9 | |
2022-07-09 | 8 | 9 | |
2022-07-10 | 8 | 9 | |
2022-07-11 | 9 | 9 | 9 |
在实际应用中,出现NULL值我们一定要特别注意,避免后面开发报表出现新的问题,所以建议尽早发现NULL,并且及时沟通商量应对方案,以上是针对不同工具实现的填充,还有更高阶的填充呢方案,我将会在后期给大家分享,记得关注哦!