数据预处理常用方法流程

文章目录

  • 数据读取和选择
  • 缺失数据
    • 找出缺失数据
    • 处理缺失数据
      • 丢弃观察值
      • 丢弃特征
      • 填充缺失数据
        • 数值变量
      • 分类变量
      • 替换缺失值
  • 异常值
    • 如何找出异常值
      • 数值变量
        • 直方图
        • 箱形图
      • 分类变量
        • 条形图
    • 如何处理异常值
  • 不必要数据
    • 不必要数据类型 1:信息不足 / 重复
    • 不必要数据类型 2:不相关
    • 不必要数据类型 3:复制
      • 复制数据类型 1:基于所有特征
      • 复制数据类型 2:基于关键特征
  • 不一致数据
    • 不一致数据类型 1:大写
    • 不一致数据类型 2:格式
    • 不一致数据类型 3:类别值
    • 不一致数据类型 4:地址

数据读取和选择

读取数据

df = pd.read_csv('.csv')

输出形状和信息

print(df.shape)
print(df.info())

选择数字列和非数字列

df_numeric = df.select_dtypes(include=[np.number])
df_non_numeric = df.select_dtypes(exclude=[np.number])

缺失数据

找出缺失数据

  • 特征较少时,缺失数据热图
cols = df.columns[:30] # first 30 columns
colours = ['#000099', '#ffff00'] # specify the colours - yellow is missing. blue is not missing.
sns.heatmap(df[cols].isnull(), cmap=sns.color_palette(colours))
  • 特征很多时,缺失数据百分比列表
missing_value = df.isnull().sum()
missing_value = missing_value[missing_value > 0] 
missing_value_rate = missing_value/len(df)
missing_value_rate.sort_values(ascending=False)
  • 特征很多时,也可以用缺失数据直方图
# first create missing indicator for features with missing data
for col in df.columns:
    missing = df[col].isnull()
    num_missing = np.sum(missing)

    if num_missing > 0:  
        print('created missing indicator for: {}'.format(col))
        df['{}_ismissing'.format(col)] = missing


# then based on the indicator, plot the histogram of missing values
ismissing_cols = [col for col in df.columns if 'ismissing' in col]
df['num_missing'] = df[ismissing_cols].sum(axis=1)

df['num_missing'].value_counts().reset_index().sort_values(by='index').plot.bar(x='index', y='num_missing')

处理缺失数据

丢弃观察值

删除样本(成行删除)

只有在我们确定缺失数据无法提供信息时,才可以执行该操作。否则,我们应当考虑其他解决方案。

# 删除了缺失值数量超过 35 的样本
# drop rows with a lot of missing values.
ind_missing = df[df['num_missing'] > 35].index
df_less_missing_rows = df.drop(ind_missing, axis=0)

丢弃特征

我们只在确定某个特征无法提供有用信息时才丢弃它。

# 大于 47% 可以考虑删除
cols_to_drop = missing_value_rate[missing_value_rate > 0.47].index
print('number of features with more than 47% missing', len(cols_to_drop))
df_less_hos_beds_raion = df.drop(cols_to_drop, axis=1)

填充缺失数据

数值变量

当特征是数值变量时,对同一特征的其他非缺失数据取平均值或中位数,用这个值来替换缺失值。

# 所有特征替换 中位数
# impute the missing values and create the missing value indicator variables for each numeric column.
df_numeric = df.select_dtypes(include=[np.number])
numeric_cols = df_numeric.columns.values

for col in numeric_cols:
    missing = df[col].isnull()
    num_missing = np.sum(missing)
    
    if num_missing > 0:  # only do the imputation for the columns that have missing values.
        print('imputing missing values for: {}'.format(col))
        df['{}_ismissing'.format(col)] = missing
        med = df[col].median()
        df[col] = df[col].fillna(med)

单个特征填充

med = df['brent'].median()
df['brent'] = df['brent'].fillna(med)

分类变量

当特征是分类变量时,用众数(最频值)来填充缺失值。

# impute the missing values and create the missing value indicator variables for each non-numeric column.
df_non_numeric = df.select_dtypes(exclude=[np.number])
non_numeric_cols = df_non_numeric.columns.values

for col in non_numeric_cols:
    missing = df[col].isnull()
    num_missing = np.sum(missing)
    
    if num_missing > 0:  # only do the imputation for the columns that have missing values.
        print('imputing missing values for: {}'.format(col))
        df['{}_ismissing'.format(col)] = missing
        
        top = df[col].describe()['top'] # impute with the most frequent value.
        df[col] = df[col].fillna(top)

替换缺失值

可以保留缺失值,使之提供有价值的信息

对于数值特征,我们可以用特定值(如 - 999)来替换缺失值

对于分类特征,我们可以添加新的带值类别,如 _MISSING_

# categorical
df['sub_area'] = df['sub_area'].fillna('_MISSING_')

# numeric
df['life_sq'] = df['life_sq'].fillna(-999)

异常值

如何找出异常值

根据特征的属性(数值或分类),使用不同的方法来研究其分布,进而检测异常值。

数值变量

直方图

df['life_sq'].hist(bins=100)

箱形图

df.boxplot(column=['life_sq'])

对于数值特征,当异常值过于独特时,箱形图无法显示该值。因此,我们可以查看其描述统计学。

df['life_sq'].describe()

分类变量

条形图

df['ecology'].value_counts().plot.bar()

其他方法:还有很多方法可以找出异常值,如散点图、z 分数和聚类

如何处理异常值

处理异常值的方法与处理缺失值有些类似:要么丢弃,要么修改,要么保留。

不必要数据

输入到模型中的所有数据应服务于项目目标。不必要数据即无法增加价值的数据。

不必要数据类型 1:信息不足 / 重复

有时一个特征不提供信息,是因为它拥有太多具备相同值的行。

为具备高比例相同值的特征创建一个列表

# 95% 的行是相同值的特征
num_rows = len(df.index)
low_information_cols = [] 

for col in df.columns:
    cnts = df[col].value_counts(dropna=False)
    top_pct = (cnts/num_rows).iloc[0]
    
    if top_pct > 0.95:
        low_information_cols.append(col)
        print('{0}: {1:.5f}%'.format(col, top_pct*100))
        print(cnts)
        print()

我们需要了解重复特征背后的原因。当它们的确无法提供有用信息时,我们就可以丢弃它。

不必要数据类型 2:不相关

数据需要为项目提供有价值的信息。如果特征与项目试图解决的问题无关,则这些特征是不相关数据。

浏览特征,找出不相关的数据,当这些特征无法服务于项目目标时,删除之。

不必要数据类型 3:复制

复制数据类型 1:基于所有特征

样本值完全重复

这种复制发生在观察值内所有特征的值均相同的情况下,很容易找出。

df_dedupped = df.drop('id', axis=1).drop_duplicates()

# there were duplicate rows
print(df.shape)
print(df_dedupped.shape)

复制数据类型 2:基于关键特征

删除基于一组唯一标识符的复制数据

我们可以设置一组关键特征作为唯一标识符,比如 timestamp、full_sq、life_sq、floor、build_year、num_room、price_doc。然后基于这些特征检查是否存在复制数据。

key = ['timestamp', 'full_sq', 'life_sq', 'floor', 'build_year', 'num_room', 'price_doc']

df.fillna(-999).groupby(key)['id'].count().sort_values(ascending=False).head(20)

处理方法:删除

key = ['timestamp', 'full_sq', 'life_sq', 'floor', 'build_year', 'num_room', 'price_doc']
df_dedupped2 = df.drop_duplicates(subset=key)

print(df.shape)
print(df_dedupped2.shape)

不一致数据

不一致数据类型 1:大写

在类别值中混用大小写是一种常见的错误。这可能带来一些问题,因为 Python 分析对大小写很敏感。

df['sub_area'].value_counts(dropna=False) / df['sub_area'].unique()

# 将所有字母设置为小写(或大写)
df['sub_area_lower'] = df['sub_area'].str.lower()
df['sub_area_lower'].value_counts(dropna=False)

不一致数据类型 2:格式

我们需要执行的另一个标准化是数据格式。比如将特征从字符串格式转换为 DateTime 格式

# 2020-05-12 
df['timestamp_dt'] = pd.to_datetime(df['timestamp'], format='%Y-%m-%d')
df['year'] = df['timestamp_dt'].dt.year
df['month'] = df['timestamp_dt'].dt.month
df['weekday'] = df['timestamp_dt'].dt.weekday

print(df['year'].value_counts(dropna=False))
print()
print(df['month'].value_counts(dropna=False))

不一致数据类型 3:类别值

分类特征的值数量有限。有时由于拼写错误等原因可能出现其他值。

由于本文使用的房地产数据集不存在这类问题,因此我们创建了一个新的数据集。例如,city 的值被错误输入为「torontoo」和「tronto」,其实二者均表示「toronto」(正确值)。

识别它们的一种简单方式是模糊逻辑(或编辑距离)。该方法可以衡量使一个值匹配另一个值需要更改的字母数量(距离)。

可以规定所有值与「toronto」的距离在 2 个字母以内的转换为正确值。

不一致数据类型 4:地址

参考资料

数据缺失、混乱、重复怎么办?最全数据清洗指南!

你可能感兴趣的:(Python,数据挖掘)