• Pandas数据清洗


    深入浅出Pandas读书笔记

    C10 Pandas数据清洗

    10.1 缺失值的认定

    10.1.1 缺失值类型

    一般使用NaN代表缺失值, 可以使用Numpy定义为np.nan或np.NaN. 在Pandas 1.0以后的版本中, 实验性的使用标量pd.NA来代表

    df = pd.DataFrame({
        'A': ['a1', 'a1', 'a2', 'a2'],
        'B': ['b1', 'b2', None, 'b2'],
        'C': [1, 2, 3, 4],
        'D': [5, 6, None, 8],
        'E': [5, None, 7, 8]
    })
    # 可以将无穷值设置为缺失值
    pd.options.mode.use_inf_as_na = True
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    10.1.2 缺失值判断

    df.isna()及其别名df.isnull(), df.notna()

    df.isna()
    df.D.isna()
    df.notna()
    df.D.notna()
    
    • 1
    • 2
    • 3
    • 4

    10.1.3 缺失值统计

    利用sum, 将False当做0, 将True当做1

    pd.Series([True, True, False]).sum()
    # 每列有多少个缺失值
    df.isnull().sum() # 每行 df.isnull().sum(1)
    # 总共多少个缺失值
    df.isnull().sum().sum()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    10.1.4 缺失值筛选

    # 筛选有缺失值的行
    df[df.isnull().any(1)]
    # 有缺失值的列
    df.loc[:, df.isnull().any(0)]
    
    • 1
    • 2
    • 3
    • 4

    10.1.5 NA标量

    pd.NA 它代表空整数, 空布尔, 空字符. pd.NA的目标是提供一个缺失值的指示器, 该提示器可以在各种数中一致使用(而不是np.nan, None, 或者pd.NaT, 具体取决于数据类型)

    s = pd.Series([1, 2, None, 4], dtype='Int64')
    s[2] is pd.NA # True
    
    • 1
    • 2

    10.1.6 时间数据中的缺失值

    Pandas提供了一个NaT来表示, 并且NaT和NaN是兼容的

    # None 根据整体的数据类型, 自动推断为NaT
    pd.Series([pd.Timestamp('20200101'), None, pd.Timestamp('20200103')])
    
    • 1
    • 2

    10.1.7 整型数据中的缺失值

    pd.Series([1, 2, np.nan, 4], dtype='Int64') 
    
    • 1

    10.1.8 插入缺失值

    10.2 缺失值的操作

    10.2.1 缺失值的填充 df.fillna()

    df.fillna(0)
    df.fillna('missing')
    df.one.fillna('暂无')
    df.fillna(0, limit=1) # 只替换1个
    # 将不同列的缺失值替换为不同的值
    values = {'A': 0, 'B': 1, 'C': 2, 'D': 3}
    df.fillna(value=values)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • pad / ffill 向前填充, 使用前一个有效值填充, df.fillna(method=‘ffill’)可以简写为df.ffill()
    • bfill / backfill 向后填充, 使用后一个有效值填充, df.fillna(method=‘fill’)可以简写为df.bfill()
    df.fillna(method='bfill')
    df.fillna(method='ffill')
    # 填充列的平均值
    df.fillna(df.mean())
    # 将指定列的空值替换为指定值
    df.replace({'toy': {np.nan: 100}})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    10.2.2 插值填充 interpolate线性插值

    插值interpolate是离散函数拟合的重要方法, 利用它可以根据函数在有限个点处的取值状况, 估算出函数在其他点处的近似值. Series和DataFrame对象都有interpolate()方法, 默认情况下, 该方法在缺失值处执行线性插值.它利用数学方法来估计缺失值, 对于较大的数据非常有用.

    s = pd.Series([0, 1, np.nan, 3])
    s.interpolate()
    '''
    0    0.0
    1    1.0
    2    2.0
    3    3.0
    dtype: float64
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    10.2.3 缺失值删除 df.dropna()

    df # 原数据
    '''
    	A	B	C	D	E
    0	a1	b1	1	5.0	5.0
    1	a1	b2	2	6.0	NaN
    2	a2	None	3	NaN	7.0
    3	a2	b2	4	8.0	8.0
    '''
    # 删除有缺失值的行
    df.dropna()
    '''
    	A	B	C	D	E
    0	a1	b1	1	5.0	5.0
    3	a2	b2	4	8.0	8.0
    '''
    # 删除有缺失值的列
    df.dropna(axis=1)
    '''
    	A	C
    0	a1	1
    1	a1	2
    2	a2	3
    3	a2	4
    '''
    # 删除所有值都缺失的行
    df.dropna(how='all')
    # 删除至少有2个缺失值的行
    df.dropna(thresh=2)
    # 指定判断缺失值的列范围
    df.dropna(subset=['name', 'born'])
    # 指定列的缺失值删除
    df.col.dropna()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    10.2.4 缺失值参与计算

    加法会忽略缺失值, 或者将其按0处理
    cumsum()和cumprod()会忽略NA值, 但值会保留在序列中, 可以使用skipna=False跳过有缺失值的计算并返回缺失值
    df.count()在统计时, 缺失值不计数
    缺失值在做聚合分组操作时, 如果聚合分组的列里有空值, 则会自动忽略这些值. 如果需要计入有空值的分组, 使用dropna=False

    10.3 数据替换 replace

    10.3.1 指定值替换

    s = pd.Series([0, 1, 2, 3, 4,])
    s.replace(0, 5)
    # 一一对应进行替换
    s.replace([0, 1, 2, 3, 4], [4, 3, 2, 1, 0])
    # 用字典映射对应替换值
    s.replace({0: 10, 1: 100})
    # 将a的0, b的5替换为100
    df.replace({'a': 0, 'b': 5}, 100)
    # 指定a里面的替换规则
    df.replace({'a': {0: 100, 4: 400}})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    10.3.2 使用替换方式

    # 将1, 2, 3替换为他们前一个值
    s.replace([1, 2, 3], method='ffill')
    s.replace([1, 2, 3], method='bfill') # 替换为后一个值
    
    • 1
    • 2
    • 3

    如果指定的要替换的值不存在, 则不起作用, 也不会报错, 以上的替换也适用于字符类型数据

    10.3.3 字符替换 df.replace()正则

    # 利用正则表达式将ba开头的值替换为new
    df.replace(to_replace=r'^ba.$', value='new', regex=True)
    # 如果多列规则不一, 可以按以下格式对应传入
    df.replace({'A': r'1$', 'B': r'2$'}, {'A': 'new', 'B': 'new2'}, regex=True)
    # 多个规则均替换为同样的值
    df.replace(regex=[r'^ba.$', 'foo'], value='new')
    # 多个规则及对应的替换内容
    df.replace(regex={r'^ba.$': 'new', 'foo': 'xyz'})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    10.3.4 缺失值替换

    列如我们可以先将无效的值替换为nan, 再进行缺失值处理

    d = {'a': list(range(4)), 
         'b': list('ab..'),
         'c': ['a', 'b', np.nan, 'd']
        }
    df = pd.DataFrame(d)
    # 将.替换为NaN
    df.replace('.', np.nan)
    # 对应替换, a换b, 点换NaN
    df.replace(['a', '.'], ['b', np.nan])
    # a后面加上stuff
    df.replace([r'\.', r'(a)'], ['dot', r'\1stuff'], regex=True)
    # b中的点替换为np.nan
    df.replace({'b': '.'}, {'b': np.nan})
    # b列的b替换为空
    df.replace({'b': {'b': ''}})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    10.3.5 数字替换

    # 生成数据
    df = pd.DataFrame(np.random.rand(10, 2))
    df[np.random.rand(df.shape[0]) > 0.5] = 1.5 # 将某些数字改成1.5
    df.replace(1.5, np.nan) # 将1.5 修改为np.nan
    df.replace([1.5, df.iloc[0, 0]], [np.nan, 'a']) # 将1.5改成NaN, 将左上角改成'a'
    
    • 1
    • 2
    • 3
    • 4
    • 5

    10.3.6 数据修剪

    对于数据中存在的极端值, 过大或者过小, 可以使用df.clip(lower, upper)来修剪, 当数据大于upper时使用upper的值, 小于lower使用lower的值, 与numpy.clip方法一样

    df = pd.DataFrame({'a': [-1, 2, 5], 'b': [6, 1, -3]})
    df.clip(0, 3)
    
    • 1
    • 2

    10.4 重复值及删除数据

    10.4.1 重复值识别 df.duplicated()

    df.duplicated(subset=None, keep='first')
    
    • 1

    它可以返回表示重复行的布尔值序列, 默认为一行的所有内容, subset可以指定列, keep参数用来确定要标记的重复值

    • first
    • last
    • False
    df = pd.DataFrame({'A': ['x', 'x', 'z'], 'B': ['x', 'x', 'x'], 'C': [1, 1, 2]})
    df
    '''
    	A	B	C
    0	x	x	1
    1	x	x	1
    2	z	x	2
    '''
    # 全行检测, 除第一次出现的外, 重复的为True
    df.duplicated()
    '''
    0    False
    1     True
    2    False
    dtype: bool
    '''
    # 除最后一次出现的外, 重复的True
    df.duplicated(keep='last')
    '''
    0     True
    1    False
    2    False
    dtype: bool
    '''
    # 所有重复的都为True
    df.duplicated(keep=False)
    '''
    0     True
    1     True
    2    False
    dtype: bool
    '''
    # 指定列检测
    df.duplicated(subset=['B'], keep=False)
    '''
    0    True
    1    True
    2    True
    dtype: bool
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    10.4.2 删除重复值 df.drop_duplicates()

    df.drop_duplicates(subset=None, keep='first', inplace=False, ignore_index=False)
    
    • 1

    参数说明

    • subset 指定的标签或标签序列, 仅删除这些列重复值, 默认情况为所有列
    • keep
      • first 保留一地刺出现的重复值
      • last 最后
      • False 删除所有重复值
    • inplace
    • ignore_index 处理后, 重新分配自然索引

    10.4.3 删除数据 df.drop()

    df.drop()通过指定标签名称和相应的轴, 或直接给定索引或列名称来删除行或列, 使用多层索引时, 可以通过指定级别来删除不同级别上的标签

    df.drop(labels=None, axis=0, index=None, columns=None, level=None, inplace=False, errors='raise')
    
    • 1

    参数说明

    • labels 要删除的列或者行, 如果要删除多个, 传入列表
    • axis
    • index
    • column
    • level 索引层级, 将删除此层级
    • inplace
    • errors ignore或者raise, 默认raise, 如果为ignore, 则容忍错误, 仅删除现有标签
    df.drop([0, 1])
    '''
    A	B	C
    2	z	x	2
    '''
    df.drop(['B', 'C'], axis=1)
    df.drop(columns=['B', 'C']) # 同上
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    10.5 NumPy格式转换

    10.5.1 转换方法

    • ds.to_numpy() 可以用在Index, Series和DataFrame对象
    • s.array 为PandasArray, 用在Index和Series
      不在推荐使用pandas的values和as_matrix()

    10.5.2 DataFrame转为ndarray

    df.values和df.to_numpy()返回的是一个array类型

    df.values # 不推荐
    df.to_numpy() # 结果同上
    type(df.to_numpy()) # numpy.ndarray
    # 转换指定的列
    df[['name', 'Q1']].to_numpy()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    10.5.3 Series转为ndarray

    s.values和s.to_numpy()返回的是一个array类型

    10.5.4 df.to_records()

    10.5.5 np.array

    可以用np.array直接读取DataFrame或者Series数据, 最终也会转换为array类型

  • 相关阅读:
    SpringBoot Validation入参校验国际化
    v 3 + vite + ts 自适应布局(postcss-pxtorem)
    java三层架构/表现层-业务层-持久层
    ISE_ChipScope Pro的使用
    Java Maven项目问题整理
    JSP 购物商城系统eclipse定制开发mysql数据库BS模式java编程servlet
    银行业数据治理的实施路径——基于资产管理的视角
    初识string+简单用法(一)
    vue3将页面导出成PDF文件(完美解决图片、表格内容分割问题)
    原型设计的坑
  • 原文地址:https://blog.csdn.net/zhaoleiedu/article/details/127896740