在前几篇关于 pandas 的文章中,笔者分别介绍了:
本篇介绍数据清洗,包括删除数据、数据去重、缺失值处理,这些都是拿到一个原始数据表之后很常用的操作。
原始数据集中可能有某些行/列数据并不是需要的,此时可以只截取需要的数据,或者把不需要的直接删除。截取数据直接用查看数据的方法截取所需行/列并赋值给一个变量即可,删除数据可以用 drop 方法,单独删除某列可以用 pop 方法或者直接使用 del df[‘列名’]。其中, pop 和 del 方法都是就地删除。
df/series.drop(labels, axis=0, index, colums, level, inplace=False, errors)
labels:单个标签或列表,指定要删除的索引或列标签。
axis:与 labels 参数配合,为 0 或 ‘index’ 则删除行,为 1 或 ‘columns’ 则删除列。
index:行标签或其列表,指定删除的行。
columns:列标签或其列表,指定删除的列。
level:对于 MultiIndex,将从中删除标签的指定级别。
inplace:若为 False 则返回副本,否则执行就地操作并返回无。
errors:默认为 ‘raise’。若为 ‘ignore’,则忽略错误,仅删除现有标签 。
df.pop(item)
item :一个单列列名,指定要删除哪个列。
注意:该方法是就地删除!返回的是被删除的列。
示例如下:
import numpy as np
import pandas as pd
df = pd.DataFrame(data = [(1, 144.5, np.nan, 33, 'M', 78.5),
(2, 167.2, 5.4, 45, 'M', np.nan),
(3, 124.1, 5.2, 23, 'F', 66.5),
(4, 144.5, np.nan, 33, 'M', 80),
(5, 133.2, 5.7, 54, 'F', np.nan),
(3, 124.1, 5.2, 23, 'F', 66.5),
(5, 129.2, 5.3, 42, 'M', 69)], columns=['id','weight','height','age','gender','score'])
df.drop([2,5]) # 删除索引为2和5的行
df.drop(labels=['weight','height'], axis=1) # 删除 weight 列和 height 列
df.drop(index=[2,5], columns=['weight','height']) # 删除索引为2、5的行和 weight 列、 height 列
df.pop('age') # 就地删除 age 列并返回该列
del df['height'] # 就地删除 height列,无返回
原始数据集中可能包含所有列或者部分列完全相同的行,这可能是完全多余的,保留它们对后续处理无益,此时就需要去重。可以用 duplicated 方法看看哪些行有重复值,或者直接用 drop_duplicates 方法去重。
df.duplicated(subset, keep=first)
或者 series.duplicated(keep=first)
subset:给出了考虑哪些列的重复值。默认考虑所有列。
keep:若为 ‘first’ ,则对于重复数据,第一次出现时标记为 False,后面出现时标记为 True;若为 ‘last’ ,则对于重复数据,最后一次出现时标记为 False,前面出现时标记为 True;若为 False,则对于重复数据,所有出现的地方都标记为 True。
df.drop_duplicates(subset, keep='first', inplace=False, igore_index=False)
或者 series.drop_duplicates(keep='first', inplace=False)
subset、keep:同上。
inplace:如果为 True,则原地修改。否则返回去重后的对象。
示例如下:
df.duplicated() # 显示哪些行是重复的,返回一个元素为布尔值的 Series
df.duplicated(subset=['id','age'], keep='last') # 显示哪些行的id和age值有重复,最后一次重复值标记为False
df.drop_duplicates() # 去除重复行
df.drop_duplicates(subset=['age','gender'], keep='first') # 去除 age 和 gender 值有重复的行,只保留第一次的值
原始数据集可能会包含缺失数据,在 Pandas 中用来自 NumPy 库的 NaN/NAN/nan 表示缺失值。缺失值和其它类型的数据不同,它毫无意义,NaN 不等于0,也不等于空串。两个 NaN 也不相等,因此为了后续处理需要对缺失值进行处理。查看是否有缺失值可以用 isna / isnull / notna / notnull 方法,处理方法主要有:删除(dropna)、填充(fillna)、替换(replace)、插值(interpolate):
df/series.isnull()
或者 df/series.isna()
返回同 shape 的 bool 值的 DataFrame/Series,无参。
df/series.notnull()
或者 df/series.notna()
同上。
df.dropna(axis=0, how='any', thresh, subset, inplace=False)
或者 series.dropna(axis=0, inplace=False, how)
axis:如果为 0/‘index’,则沿着0轴过滤;如果为 1/‘columns’,则沿着1轴过滤。
how:如果为 ‘any’,则如果某行/列中只要有任何 NaN,则删除该行/列;如果为’all’,则如果某行/列数据全部为 NaN 才删除该行/列。
thresh:一个整数,要求该行/列必须有 thresh 个非 NaN 才保留,比how的优先级高。
subset:指定考虑行/列的哪些子集上的NaN。
inplace:若为True,则原地修改,否则返回处理后的数据。
df/series.fillna(value, method, axis, inplace=False, limit, downcast)
value:一个标量、字典、Series 或者 DataFrame。注意:value 与 method 只能指定其中之一,不能同时提供。如果为标量,则它指定了填充NaN的数据;如果为Series/dict,则它指定了填充每个 index 的数据;如果为 DataFrame,则它指定了填充每个 DataFrame 单元的数据。
method:指定填充方式。可以为:‘backfill’/‘bfill’ (使用下一个可用的有效值填充);‘ffill’/‘pad’ (使用前一个可用的有效值填充)。
axis、inplace:同上。
limit:一个整数。如果指定了 method,则当有连续的N个NaN时,只有其中的limit个NaN会被填充。
downcast:指定类型转换。
df.replace(to_replace, value, inplace=False, limit, regex=False, method='pad')
to_replace:一个字符串、正则表达式、列表、字典、Series、数值、None,指定需要被替换的那些值。
value:指定替换值。
inplace:同上。
limit:一个整数,指定了连续填充的最大跨度。
regex:一个布尔值,是否正则替换。若为True,则 to_replace 必须是字符串。
method:指定填充类型,可以为’pad’/‘ffill’/‘bfill’,当 to_replace 是个列表时该参数有效。
df.interpolate(method='linear', axis=0, limit, inplace=False, limit_direction, limit_area, downcast, **kwargs)
method:指定插值的方法。'linear’表示线性插值,支持多级索引,还有其他 scipy 插值函数。
axis、limit、inplace、downcast:同上。
limit_direction:当设定了 limit 时,指定处理前面还是后面 limit 个NaN,可以为 ‘forward’/‘backward’/‘both’。
其他参数传递给 scipy 插值函数。
示例如下:
df.isna() # 是否是缺失值,返回 shape 相同的元素为布尔值的 DataFrame,等价于 df.isnull()
df.notna() # 是否不是缺失值,等价于 df.notnull()
df.dropna() # 删除有缺失值的行
df.dropna(subset=['id','score']) # 删除 id/score 列中有缺失值的行
df.fillna(0) # 缺失值用0填充
df.fillna({'height':5,'score':60}) # height 列的缺失值用5填充,score 列的用60填充
df.fillna(method='ffill') # 使用缺失值的前一个可用的有效值填充
df.replace(np.nan, 0) # 缺失值用0替换
df.replace(np.nan, {'height':5,'score':60}) # height 列的缺失值用5替换,score 列的用60替换
df.replace({'height':{np.nan:5}, 'score':{np.nan: 60}}) # 同上
df.replace(['M','F'],['Man','Woman'], regex=False) # 把M替换成 Man,把F替换成 Woman,非正则替换
df.interpolate() # 用线性插值填充缺失值
df.interpolate(method='linear', limit_direction='backward') # 后向线性插值填充缺失值
df.interpolate(method='quadratic') # 二次插值填充缺失值
以上。