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

10.1.2 缺失值判断

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

df.isna()
df.D.isna()
df.notna()
df.D.notna()

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()

10.1.4 缺失值筛选

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

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

10.1.6 时间数据中的缺失值

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

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

10.1.7 整型数据中的缺失值

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

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)
  • 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}})

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
'''

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()

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}})

10.3.2 使用替换方式

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

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

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'})

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': ''}})

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'

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)

10.4 重复值及删除数据

10.4.1 重复值识别 df.duplicated()

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

它可以返回表示重复行的布尔值序列, 默认为一行的所有内容, 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
'''

10.4.2 删除重复值 df.drop_duplicates()

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

参数说明

  • 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')

参数说明

  • 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']) # 同上

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()

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类型

你可能感兴趣的:(深入浅出Pandas,pandas,python,数据分析)