缺失值处理

缺失值表示:NaN
产生:读取文件空单元格、计算异常、数据丢失
处理方式:

  1. 首先获取缺失值的标记方式;
  2. 标记方式为NaN,判断数据中是否有缺失值,若有进行删除或替换;
  3. 存在其他标记方式,例如特殊符号“?/-”,先将特殊符号转成NaN。

查看

  1. 查看是否有缺失
pd.isnull(df) # 效果同下,判断每列每个值是否为空,为空则为True
df.isnull()   # 查看缺失值
df.notnull()  # 查看非缺失值
  1. 统计每列缺失数量(最常用)
df.isnull().sum()
  1. 查看缺失比例(%)
df.isnull().mean() * 100
  1. 只看有缺失的列
df.loc[:, df.isnull().any()]

删除

  • 删除 含有缺失值的行
# 返回新结果,若要对原始数据直接进行修改,须通过inplace=True参数
df.dropna()
  • 删除 含有缺失值的列
df.dropna(axis=1)
  • 只删除 全部都是 NaN 的行
df.dropna(how='all')

填充

  • 统一填充固定值,例如 0
df.fillna(0)
  • 用 均值 填充(数值列常用)
df['年龄'].fillna(df['年龄'].mean())

替换指定值为缺失值

# 把特殊符号(如?/-/未知)转成 NaN
df.replace(['?', '-', '未知'], np.nan)

数据合并

pd.concat()-上下 / 左右拼接

参数:

  • axis=0:默认,上下拼接(行增加)
  • axis=1:左右拼接(列增加)
  • ignore_index=True:重置行索引(必写)
import pandas as pd

df1 = pd.DataFrame({'name':['张三','李四'],'age':[20,25]})
df2 = pd.DataFrame({'name':['王五','赵六'],'age':[30,28]})

# 上下拼接(竖着拼)
df = pd.concat([df1, df2], ignore_index=True)

pd.merge()-左右关联

根据共同列(如 ID、姓名),横向关联。
参数:

  • how:连接方式,inner内连接(交集),left左连接(以左表为准),right右连接(以右表为准),outer全连接(并集);
  • on:关联列名(必须一致);
  • left_on / right_on:列名不一样时用。
df1 = pd.DataFrame({'name':['张三','李四'],'dept_id':[1,2]})
df2 = pd.DataFrame({'id':[1,2],'dept_name':['技术','产品']})

# 左连接:以df1为准,关联部门
df = pd.merge(df1, df2, left_on='dept_id', right_on='id', how='left')

df.join()-按索引合并

直接根据行索引合并

df1.join(df2)

数据分组

分组

import pandas as pd

df = pd.DataFrame({
    '姓名': ['张三','李四','王五','赵六','钱七'],
    '部门': ['技术','产品','技术','产品','技术'],
    '岗位': ['技术1','产品1','技术2','产品1','技术2'],
    '工资': [5000,7000,9000,8000,6000],
    '年龄': [20,25,30,28,22]
})

# 只分组,不计算
g = df.groupby('部门')  

# 查看有哪些分组(组名)
g.groups.keys()
# 获取某一组的所有数据,直接返回该组的DataFrame对象
g.get_group('技术')

分组+聚合

——格式

df.groupby("分组列")["统计列"].聚合函数()

——示例

# 1. 按部门分组,同时统计工资、年龄
df.groupby('部门')[['工资','年龄']].mean()

# 2. 按多个字段分组
df.groupby(['部门','岗位'])['工资'].sum()

# 3. 一次用多个聚合函数
df.groupby('部门')['工资'].agg(['mean','sum','max','count'])

# 4. 不同列用不同聚合函数
df.groupby('部门').agg({
    '工资': ['mean','sum'],
    '年龄': 'max'
})

# 5. 分组后变回正常表(reset_index)
df.groupby('部门')['工资'].mean().reset_index()

分组+过滤

对每一个分组进行判断,满足条件就保留整个组,不满足就整个组删掉。

df.groupby("分组字段").filter(lambda x: 对组x的条件)

# 只保留 平均工资 > 6000 的组
res = df.groupby('部门').filter(lambda x: x['工资'].mean() > 6000)
print(res)

交叉表与透视表

交叉表(pd.crosstab)

专门用来做频次统计(计数)

import pandas as pd

df = pd.DataFrame({
    '部门':['技术','技术','产品','产品','市场'],
    '学历':['本科','硕士','本科','本科','硕士']
})

# 交叉表:行=部门,列=学历,值=人数
pd.crosstab(df['部门'], df['学历'])

透视表

多维度数据聚合与汇总工具,基于行维度(index)、列维度(columns) 对数据进行分组(GROUP BY),并对指定数值字段执行聚合计算(求和、均值、计数、标准差等),最终生成多维汇总报表。

pd.pivot_table(
    data,                # 输入数据集(DataFrame)
    index=None,          # 行维度(分组字段,对应 GROUP BY 维度1)
    columns=None,        # 列维度(分组字段,对应 GROUP BY 维度2)
    values=None,         # 待聚合的数值字段(要计算的指标)
    aggfunc='mean',      # 聚合函数(mean/sum/count/std/sum/min/max)
    fill_value=None,     # 缺失值填充
    margins=False,       # 是否添加总计行/列
    dropna=True,         # 是否删除含缺失值的列
    margins_name='Total'# 总计行列名称
)

# 示例,按照部门和学历,统计平均薪资
pd.pivot_table(
    df,
    index='部门',
    columns='学历',
    values='工资',
    aggfunc='mean'
)

更多推荐