【编程实践】Joyful-Pandas(下)Task01(第六章):缺失数据

【编程实践】Joyful-Pandas(下)Task01(第六章):缺失数据

  • Datawhale学习要求
  • Nullable类型与NA符号
  • 缺失数据的运算与分组
  • 填充与剔除
  • 插值(interpolation)
  • 问题
  • 练习

缺失数据和文本数据(尤其是混杂性文本)是数据预处理中比较麻烦的类型,本章节聚焦于缺失数据。

Nullable类型和String类型可能在未来成为Pandas的主流数据类型。

Datawhale学习要求

理论部分

  • 理解Nullable类型与NA符号
  • 掌握缺失值的填充与剔除
  • 掌握常见缺失值插值方法

练习部分

  • 两道缺失数据练习题

Nullable类型与NA符号

Pandas 1.0之前的版本:三种缺失符号

缺失符号 np.nan None np.NaT
类型 float64 Nonetype pandas._libs.tslibs.nattype.NaTType
equal的时候是否会包括在内 不包括 包括 不包括
某列出现该值的类型 1.数值型,布尔型统一转换为float64;2.字符型统一转换为O(object类型) 1.None传入数值型自动变换为np.nan;None传入时间型变量自动变换为np.NaT;2.None传入布尔类型,不改变原布尔列表;3.None传入字符型为NoneType 时间型变量类型不改变

** Pandas 1.0之后的版本:Nullable类型与NA符号**
官方鼓励用户使用新的数据类型和缺失类型pd.NA

缺失数据的运算与分组

加号与乘号规则

  • 使用加法时,缺失值为0
  • 使用乘法时,缺失值为1
  • 使用累计函数时,缺失值自动略过

groupby方法中的缺失值

  • 自动忽略为缺失值的组

填充与剔除

  • fillna方法
  • dropna方法

插值(interpolation)

  • 线性插值
  • 高级插值方法:样条插值、多项式插值、阿基玛插值等
  • 限制参数

问题

问题一:如何删除缺失值占比超过25%的列?

// 
import pandas as pd
import numpy as np
# 创建一个有不同缺失情况的dataframe对象
df_d = pd.DataFrame({'A':[np.nan,np.nan,np.nan,np.nan,np.nan,np.nan],'B':[np.nan,np.nan,np.nan,np.nan,np.nan,2],'C':[np.nan,np.nan,np.nan,np.nan,2,1],'D':[np.nan,np.nan,np.nan,3,2,1],'E':[np.nan,np.nan,4,3,2,1],'F':[np.nan,5,4,3,2,1],'G':[6,5,4,3,2,1]})
# 首先将其中所有全为缺失值的列直接删除
df_d_new_1 = df_d.dropna(axis = 1, how = 'all')
# 统计不同列缺失值数量,s是一个series对象
s = df_d_new_1.isna().sum()
# 计算整个对象的行数
row = df_d_new_1.shape[0]
# 通过索引的循环,分别计算每一列的缺失值比例,并和原dataframe行数的四分之一进行比较,大于四分之一的就会被删除
for index in s.index:
    if (int(s['{}'.format(index)])) > (row/4):
        df_d_new_1 = df_d_new_1.drop(columns = '{}'.format(index))
        print('finished')
print(df_d_new_1)

问题二:什么是Nullable类型?请谈谈为什么要引入这个设计?
这是一种具有相对比较独立属性特征的缺失值类型
统一目前Pandas中比较混乱的缺失值处理符号,同时规范缺失值处理过程中对于原dataframe对象,series对象数据类型的影响

问题三:对于一份有缺失值的数据,可以采取哪些策略或方法深化对它的了解?

  • 用 info() 和 isna() 方法了解缺失值分布
  • 结果返回
  • 通过遍历了解整个dataframe对象中的所有行列缺失值分布状态

练习

练习一
现有一份虚拟数据集,列类型分别为string/浮点/整型,请解决如下问题:
(a)请以列类型读入数据,并选出C为缺失值的行。
(b)现需要将A中的部分单元转为缺失值,单元格中的最小转换概率为25%,且概率大小与所在行B列单元的值成正比。
练习1解答

A B C
0 not_NaN 0.922 4.0
1 not_NaN 0.700 NaN
2 not_NaN 0.503 8.0
3 not_NaN 0.938 4.0
4 not_NaN 0.952 10.0
// 
pd.read_csv('data/Missing_data_one.csv').head()

import pandas as pd
import numpy as np
import random
# 导入数据
df = pd.read_csv('data/Missing_data_one.csv').convert_dtypes()
# 筛选出C列存在缺失值的行
df_1 = df[df['C'].isna()]
print(df_1.head())
# 将前面两列的名称存入变量
column_1 = df.columns.values[0]
column_2 = df.columns.values[1]
# 确定B列的最大/最小值,方便后面概率的计算
min = int(df['{}'.format(column_2)].idxmin())
max = int(df['{}'.format(column_2)].idxmax())
# 通过循环遍历整个A列
for index in range(df.shape[0]):
    # 生成一个0-1之间的随机浮点数
    rand_num = random.random()
    # 通过与A列该元素同行的B列数字大小确定其被填充为缺失值的概率,最小为25%,最大为100%,概率大小随着B列数字的大小变化而变化
    probability = 0.25 + 0.75 * (float(df.at[index,'{}'.format(column_2)])-min)/(max-min)
    # 如果随机生成的浮点数rand_num没有落在概率范围内,则表示该次命中概率,A列相应元素被填充为缺失值
    if rand_num < probability:
        df.loc[index,'{}'.format(column_1)] = pd.NA
print(df.head())
print('==================')

练习二
现有一份缺失的数据集,记录了36个人来自的地区、身高、体重、年龄和工资,请解决如下问题:
(a)统计各列缺失的比例并选出在后三列中至少有两个非缺失值的行。¶
(b)请结合身高列和地区列中的数据,对体重进行合理插值。
练习2解答

编号 地区 身高 体重 年龄 工资
0 1 A 157.50 NaN 47.0 15905.0
1 2 B 202.00 91.80 25.0 NaN
2 3 C 169.09 62.18 NaN NaN
3 4 A 166.61 59.95 77.0 5434.0
4 5 B 185.19 NaN 62.0 4242.0
//
pd.read_csv('data/Missing_data_two.csv').head()

import pandas as pd
import numpy as np
from scipy import interpolate
# 读取数据
df = pd.read_csv('data/Missing_data_two.csv').convert_dtypes()
# 将列名称存入一个列表
columns = df.columns.values.tolist()
# 定义一个空的字典
Pom_values = {}
# 计算每列缺失值比例,并存入一个字典,与列名相对应
for column in columns:
    num = int(df.shape[0])
    Pom_values['{}'.format(column)] = 1 - ((int(df['{}'.format(column)].count()))/num)
# 创建一个空的列表,用于存储后三列中至少有两个非缺失值的行索引
index_list = []
# 遍历每行,分别计算其后三列的缺失值数量(因为除了后三列,其他列都没有缺失值存在,就直接遍历了整行内容,没有考虑效率)
for index in range(df.shape[0]):
    num = 0
    for column in columns:
        if pd.isnull(df.at[index,'{}'.format(column)]) :
            num += 1
    if num <= 1:
        index_list.append(index)
print(index_list)

print('=====')

#print(df)


df_1 = df.sort_values(by = ['地区', '身高'])

print(df_1)
print('=====')
# 首先将“地区”列中的所有不同元素存入一个列表
List_type = df['地区'].unique()
# 根据不同的地区元素将原来的大dataframe拆分成三个小的dataframe,在小的对象中,只有一个地区属性,并按身高进行排序
data0 = df[df['地区'].isin([List_type[0]])].sort_values(by = ['身高'])
data1 = df[df['地区'].isin([List_type[1]])].sort_values(by = ['身高'])
data2 = df[df['地区'].isin([List_type[2]])].sort_values(by = ['身高'])
# 在每个地区中,分别进行线性插值
#data0['体重'] = data0['体重'].fillna(method = 'pad')
data0['体重'] = data0['体重'].interpolate()
data1['体重'] = data1['体重'].interpolate()
data2['体重'] = data2['体重'].interpolate()
#print(data0)

result = data0.append([data1, data2])

print(result)

你可能感兴趣的:(Datawhale,python,pandas)