空值填充技巧(上)

在使用数据过程中,我们常常会遇到NULL值,对于NULL的存在,你们是否在乎呢?
空值填充技巧(上)_第1张图片

常见的场景:使用Excel进行合并单元格的数据时,将他们录入数据库或者加载到PowerBI,合并单元格的数据只显示一行有数据,其它则显示NULL,这种情况需要对数据空值进行填充,才能真正用于可视化和报表开发;

如果未处理,则可视化可能会出现下面情况:
空值填充技巧(上)_第2张图片

空值填充技巧(上)_第3张图片

实际场景:有这样一份关于企业用户数的每天记录,但由于系统原因常常出现有些天企业用户数没有进行统计,测试数据如下:

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中进行实现呢?

Mysql 实现向下或向上填充

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 实现向下或向上填充

对于空值的处理Python有专门的fillna函数处理,有兴趣的同学可以去官网进行查阅:fillna语法

在这里我们进行了简单的使用:

  • method=‘ffill’ 使用前一个不为空的值填充
  • method=‘bfill’ 使用后一个不为空的值填充
# 导入所需要的模块
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,并且及时沟通商量应对方案,以上是针对不同工具实现的填充,还有更高阶的填充呢方案,我将会在后期给大家分享,记得关注哦!

你可能感兴趣的:(数据分析,数据分析)