【干货】数据清洗的魔法:揭秘专业数据分析师的秘密武器

作为一名数据剖析师,我经常被问到:“数据剖析的要害是什么?”我的答复总是:“数据清洗。” 是的,您没有听错。在这篇文章中,我将结合多年的工作经验,详细介绍数据清洗的重要性和办法,协助您在数据剖析的道路上更进一步。

一、数据清洗的重要性

1-1. 数据质量的保证

在数据剖析进程中,数据质量是至关重要的。而数据清洗正是保证数据质量的要害进程。经过数据清洗,咱们可以去除数据中的过错、重复和不一致,然后保证数据的精确性和可靠性。

1-2. 进步剖析效率

数据清洗不仅可以保证数据质量,还可以进步数据剖析的效率。当数据会集存在很多的过错、重复和不一致时,剖析进程将变得复杂且耗时。经过数据清洗,咱们可以消除这些问题,然后加快剖析速度。

二、数据清洗的常见办法

2-1. 缺失值处理

在实践工作中,数据会集经常会呈现缺失值。关于缺失值,咱们可以采用以下几种办法进行处理:

1. 删去:直接删去含有缺失值的记载。
import pandas as pd
# 1. 导入数据集为DataFrame目标
df = pd.read_csv('data.csv')
# 2. 删去包括缺失值的行
df.dropna(inplace=True)
2. 填充:用某个值(如平均值、中位数等)填充缺失值。
# 运用平均值填充缺失值
df.fillna(df.mean(), inplace=True)
# 运用中位数填充缺失值
df.fillna(df.median(), inplace=True)
3. 插值:依据已有数据,运用插值办法预算缺失值。
a. 线性插值(Linear Interpolation)

线性插值是一种简略而有效的办法,用于在给定数据会集预算缺失值。该办法依据两个已知数据点之间的线性联系来猜测不知道值。以下是运用线性插值办法预算缺失值的进程:

  1. 确认已知数据点:找到缺失值邻近的两个已知数据点。这些数据点一般是缺失值的前一个和后一个数据点。
  2. 核算斜率:运用这两个已知数据点核算线性插值的斜率。斜率可以经过以下公式核算:斜率 = (y2 – y1) / (x2 – x1) 其间,(x1, y1) 和 (x2, y2) 别离是已知数据点的坐标。
  3. 核算不知道值的 y 坐标:运用斜率和已知数据点之一(例如 (x1, y1)),核算不知道值的 y 坐标。可以运用以下公式:y = y1 + 斜率 * (x – x1) 其间,x 是不知道值的 x 坐标。
  4. 预算缺失值:现在咱们现已得到了预算值的 y 坐标,即缺失值的预算成果。

需要留意的是,线性插值办法假定数据点之间的联系是线性的。假如数据具有非线性联系,这种办法或许不会产生精确的估计。在这种情况下,可以考虑运用其他插值办法,如多项式插值或样条插值。

# 咱们有三个已知的数据点:(0, 1), (2, 3) 和 (4, 5)。咱们想要预算x坐标为3的缺失值。
import numpy as np
# 已知数据点
x_known = np.array([0, 2, 4])
y_known = np.array([1, 3, 5])
# 缺失值的x坐标
x_missing = 3
# 运用线性插值预算缺失值
y_missing = np.interp(x_missing, x_known, y_known)
print("预算的缺失值:", y_missing) # 4.0
b. 多项式插值(Polynomial interpolation) :

多项式插值是一种经过拟合一个多项式函数来预算缺失值的办法。这个多项式函数会经过一切已知数据点,并用来猜测不知道值。给定n个已知数据点,可以找到一个n-1阶的多项式函数,使其经过一切数据点。多项式插值的公式如下:

P(x) = a0 + a1 * x + a2 * x^2 + … + an * x^n

P(x) = a0 + a1 * x + a2 * x^2 + … + an * x^n

其间,a0, a1, …, an是多项式的系数。

多项式插值或许会产生较好的估计,特别是当数据具有非线性联系时。但是,高阶多项式或许会导致过拟合问题,即在已知数据点之间的猜测或许较好,但在已知数据点之外的猜测或许较差。

import numpy as np
# 已知数据点
x_known = np.array([0, 2, 4])
y_known = np.array([1, 3, 5])
# 缺失值的x坐标
x_missing = 3
# 运用多项式插值预算缺失值
degree = len(x_known) - 1
coefficients = np.polyfit(x_known, y_known, degree)
y_missing = np.polyval(coefficients, x_missing)
print("预算的缺失值:", y_missing)  #预算的缺失值: 4.000000000000001
c. 样条插值(Spline interpolation):

样条插值是一种经过拟合一组分段多项式函数(一般为三次多项式)来预算缺失值的办法。样条插值可以在数据点之间产生滑润的曲线,而且一般具有较好的插值作用。样条插值的一个优点是它可以更好地处理非线性数据。

在样条插值中,数据点之间的每个区间都由一个多项式函数(如三次多项式)表明。这些多项式函数需要满足必定的条件,以保证整个插值曲线的滑润性和连续性。例如,在相邻多项式的交界处,它们的函数值、一阶导数和二阶导数都相等。

常见的样条插值办法有线性样条插值(线性分段函数)、二次样条插值(二次分段函数)和三次样条插值(三次分段函数)。其间,三次样条插值最为常用,由于它可以在保持滑润性和连续性的一同,较好地拟合数据点。

# 由于数据量较少我运用了线性样条插值(kind='linear')
# 假如您有更多的数据点,可以尝试运用三次样条插值(kind='cubic')
import numpy as np
from scipy.interpolate import interp1d
# 已知数据点
x_known = np.array([0, 2, 4])
y_known = np.array([1, 3, 5])
# 缺失值的x坐标
x_missing = 3
# 运用线性样条插值预算缺失值
linear_spline = interp1d(x_known, y_known, kind='linear')
y_missing = linear_spline(x_missing)
print("预算的缺失值:", y_missing)  # 预算的缺失值: 4.0

2-2. 异常值检测与处理

数据中的异常值或许会对剖析成果产生较大影响。咱们可以经过以下办法检测并处理异常值:

1.箱线图:经过制作箱线图,可以直观地发现数据中的异常值。

【干货】数据清洗的魔法:揭秘专业数据分析师的秘密武器

'''
咱们首要导入了numpy、matplotlib和seaborn库。
然后,咱们生成了一个包括100个随机数的数据集。
接着,咱们别离运用matplotlib的boxplot()函数和seaborn的boxplot()函数制作了箱线图。
最终,咱们运用plt.show()显现箱线图。
'''
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 生成一个随机数据集
data = np.random.randn(100)
# 运用matplotlib制作箱线图
plt.boxplot(data)
plt.title('Boxplot using matplotlib')
plt.show()
# 运用seaborn制作箱线图
sns.boxplot(data)
plt.title('Boxplot using seaborn')
plt.show()
2. 3准则:

3准则(也称为三西格玛准则)是一种依据正态散布的异常值检测办法。该准则认为,在正态散布的数据会集,大约68%的数据点坐落均值邻近的一个标准差规模内,大约95%的数据点坐落均值邻近的两个标准差规模内,而大约99.7%的数据点坐落均值邻近的三个标准差规模内。因而,超出均值邻近三个标准差规模的数据点可以被认为是异常值。

以下是运用3准则检测异常值的进程:

  1. 核算数据集的均值()和标准差()。
  2. 关于每个数据点 x,查看其是否在规模 (-3) 到 (+3) 内。假如不在这个规模内,则将其视为异常值。

以下是一个运用Python完成的比如:

import numpy as np
# 示例数据集(包括异常值)
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 100])
# 核算均值和标准差
mean = np.mean(data)
std_dev = np.std(data)
# 界说异常值检测函数
def is_outlier(x, mean, std_dev):
   return (x < mean - 3 * std_dev) or (x > mean + 3 * std_dev)
# 检测异常值
outliers = [x for x in data if is_outlier(x, mean, std_dev)]
print("异常值:", outliers)  # 异常值:100
3. IQR办法(Interquartile Range):

IQR是指数据会集第三四分位数(Q3)与第一四分位数(Q1)之间的间隔。IQR表明了数据会集50%的数据的散布规模,对异常值不灵敏。在IQR办法中,异常值被界说为低于Q1 – 1.5 * IQR或高于Q3 + 1.5 * IQR的数据点。运用IQR办法检测异常值的进程:

  1. 核算数据集的第一四分位数(Q1)和第三四分位数(Q3)。
  2. 核算IQR:IQR = Q3 – Q1。核算 IQR:IQR = Q3 – Q1。
  3. 核算异常值的下界和上界:下界 = Q1 – 1.5 * IQR,上界 = Q3 + 1.5 * IQR。

关于每个数据点,查看其是否在下界和上界之间。假如不在这个规模内,则将其视为异常值。

import numpy as np
# 示例数据集
data = np.array([1, 2, 3, 4, 5, 6, 7, 100])
# 核算Q1和Q3
Q1 = np.percentile(data, 25)
Q3 = np.percentile(data, 75)
# 核算IQR
IQR = Q3 - Q1
# 界说异常值检测函数
def is_outlier_iqr(x, Q1, Q3, IQR):
   return (x < Q1 - 1.5 * IQR) or (x > Q3 + 1.5 * IQR)
# 检测异常值
outliers_iqr = [x for x in data if is_outlier_iqr(x, Q1, Q3, IQR)]
print("IQR办法异常值:", outliers_iqr)  #IQR办法异常值:[100]
4. 图基围栏(Tukey Fences):

Tukey Fences是一种异常值检测办法,由统计学家John Tukey提出。这种办法与IQR办法十分相似,但答应运用不同的倍数因子(k)来界说异常值规模。异常值被界说为低于Q1 – k * IQR或高于Q3 + k * IQR的数据点。一般,k的值为1.5(与IQR办法相同)或3(对异常值界说更严格)。运用Tukey Fences检测异常值的进程与IQR办法相同,只需将1.5替换为所选的k值。

import numpy as np
# 示例数据集
data = np.array([1, 2, 3, 4, 5, 6, 7, 100])
# 核算Q1和Q3
Q1 = np.percentile(data, 25)
Q3 = np.percentile(data, 75)
# 核算IQR
IQR = Q3 - Q1
# 界说异常值检测函数
def is_outlier(x, Q1, Q3, IQR, k):
   return (x < Q1 - k * IQR) or (x > Q3 + k * IQR)
# 运用IQR办法(k=1.5)检测异常值
outliers_iqr = [x for x in data if is_outlier(x, Q1, Q3, IQR, 1.5)]
# 运用Tukey Fences(k=3)检测异常值
outliers_tukey = [x for x in data if is_outlier(x, Q1, Q3, IQR, 3)]
print("IQR办法异常值:", outliers_iqr)
print("Tukey Fences异常值:", outliers_tukey)

2-3 .重复值处理

重复值会导致数据剖析成果呈现误差。咱们可以经过以下办法处理重复值:

  • 去重:直接删去重复记载。
  • 兼并:将重复记载兼并为一条记载。
'''
首要创立了两个示例数据集并将它们转化为pandas DataFrame。
然后,运用pd.concat()函数将两个数据集兼并。
最终,运用drop_duplicates()函数依据ID列去除重复的数据。
'''
import pandas as pd
# 示例数据集
data1 = {
   'ID': [1, 2, 3, 4],
   'Name': ['Alice', 'Bob', 'Charlie', 'David']
}
data2 = {
   'ID': [3, 4, 5, 6],
   'Name': ['Charlie', 'David', 'Eva', 'Frank']
}
# 将字典转化为pandas DataFrame
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)
# 数据兼并
merged_data = pd.concat([df1, df2], ignore_index=True)
print("兼并后的数据:")
print(merged_data)
# 数据去重
deduplicated_data = merged_data.drop_duplicates(subset='ID', keep='first')
print("去重后的数据:")
print(deduplicated_data)

2-4. 数据转化

数据转化是将数据从一种格式转化为另一种格式的进程。常见的数据转化办法有:

1. 归一化:将数据缩放到一个特定的规模内,如[0, 1]。
2. 标准化(Z-score归一化):将数据转化为均值为0、标准差为1的标准正态散布。

数据归一化(Normalization)是一种数据预处理技术,用于将不同标准和规模的数值特征转化为相同的标准或规模。这样可以消除数值特征之间的差异,使得模型更容易学习和比较特征。数据归一化一般在机器学习和数据发掘中运用,特别是在涉及间隔衡量(如K-近邻算法、K-均值聚类)或梯度下降优化(如线性回归、神经网络)的算法中。

常见的数据归一化办法有:

a. 最小最大归一化(Min-Max Scaling):

最小最大归一化将原始数据线性缩放到一个指定的规模(一般为[0, 1])。公式如下:

X_norm = (X – X_min) / (X_max – X_min)

其间,X是原始数据,X_min和X_max别离是数据的最小值和最大值,X_norm是归一化后的数据。

b. Z-score归一化(Standardization):

Z-score归一化将原始数据转化为均值为0,标准差为1的散布。公式如下:

X_norm = (X – ) /

其间,X是原始数据,是数据的均值,是数据的标准差,X_norm是归一化后的数据。

import numpy as np
# 示例数据集
data = np.array([1, 2, 3, 4, 5, 6, 7, 100])
# 最小最大归一化
def min_max_scaling(data):
    return (data - np.min(data)) / (np.max(data) - np.min(data))
normalized_data_min_max = min_max_scaling(data)
print("最小最大归一化成果:", normalized_data_min_max)
# Z-score归一化
def z_score_scaling(data):
    return (data - np.mean(data)) / np.std(data)
normalized_data_z_score = z_score_scaling(data)
print("Z-score归一化成果:", normalized_data_z_score)

在最小最大归一化中,数据被缩放到0到1的规模内。而在Z-score归一化中,数据的均值挨近0,标准差挨近1。

需要留意的是,归一化办法的挑选取决于具体的运用场景和数据特色。例如,最小最大归一化对离群值灵敏,而Z-score归一化则对离群值具有较强的鲁棒性。在实践运用中,可以依据数据特色和需求挑选适宜的归一化办法。

3. 分类数据编码:将分类数据转化为数值型数据,如独热编码。

分类数据编码是将分类变量(如文本标签或类别)转化为数值方式,以便机器学习算法可以处理这些变量。分类数据编码一般在数据预处理阶段进行,可以协助模型更好地了解和学习特征。

常见的分类数据编码办法有:

a. 标签编码(Label Encoding):

标签编码是一种简略的编码办法,将分类变量的每个仅有类别分配一个整数。这种办法适用于有序分类变量,但不适用于无序分类变量,由于整数编码或许导致算法过错地认为类别之间存在次序联系。

b. 独热编码(One-Hot Encoding):

独热编码是一种二进制编码办法,将分类变量的每个仅有类别转化为一个二进制向量。向量的长度等于类别的数量,对应于当前类别的元素设置为1,其余元素设置为0。这种办法适用于无序分类变量,但或许导致维度较高,尤其是在类别数量较多时。

以下是运用Python(pandas库)完成标签编码和独热编码的示例:

'''
别离运用标签编码和独热编码对分类变量进行了处理。
'''
import pandas as pd
# 示例数据集
data = {'Animal': ['Dog', 'Cat', 'Dog', 'Fish', 'Cat']}
df = pd.DataFrame(data)
# 标签编码
label_encoded = df['Animal'].astype('category').cat.codes
print("标签编码成果:")
print(label_encoded)
# 独热编码
one_hot_encoded = pd.get_dummies(df['Animal'], prefix='Animal')
print("独热编码成果:")
print(one_hot_encoded)

可以看到,在这个示例中,标签编码将分类变量转化为整数值,而独热编码将分类变量转化为二进制向量。在实践运用中,可以依据数据特色和需求挑选适宜的分类数据编码办法。

需要留意的是,关于依据树的模型(如决策树、随机森林、梯度提升树等),标签编码一般是足够的,由于这些模型可以处理类别之间的次序联系。但是,关于依据间隔衡量或线性模型(如K-近邻算法、逻辑回归等),独热编码一般是更好的挑选,由于它可以防止过错地引入次序联系。

另外,假如类别数量较多,可以考虑运用其他编码办法,如二进制编码(Binary Encoding)、效用编码(Effect Encoding)等,以减小编码后数据的维度。

2-5. 数据整合

数据整合是指将来自多个数据源的数据整合到一同的进程。数据整合的意图是为了获取更全面、精确的信息,然后进步数据剖析的质量。数据整合的办法一般包括数据衔接、数据叠加、数据兼并等。

在Python中,咱们可以运用pandas库进行数据整合。以下是一些常见的数据整合办法及其完成:

1. 数据衔接(Join)

数据衔接是将两个或多个数据集依照某个共同属性(键)衔接在一同。咱们可以运用pandas的merge()函数进行数据衔接。

import pandas as pd
# 创立两个示例数据集
data1 = pd.DataFrame({
    'key': ['A', 'B', 'C', 'D'],
    'value': [1, 2, 3, 4]
})
data2 = pd.DataFrame({
    'key': ['B', 'D', 'E', 'F'],
    'value': [5, 6, 7, 8]
})
# 数据衔接
result = pd.merge(data1, data2, on='key', how='inner')  # 内衔接
result_outer = pd.merge(data1, data2, on='key', how='outer')  # 外衔接
result_left = pd.merge(data1, data2, on='key', how='left')  # 左衔接
result_right = pd.merge(data1, data2, on='key', how='right')  # 右衔接
print("Inner join:", result)
print("Outer join:", result_outer)
print("Left join:", result_left)
print("Right join:", result_right)
2. 数据叠加(Concat)

数据叠加是将两个或多个具有相同结构(列名相同)的数据集按行或列方向叠加在一同。咱们可以运用pandas的concat()函数进行数据叠加。

import pandas as pd
# 创立两个示例数据集
data1 = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6]
})
data2 = pd.DataFrame({
    'A': [7, 8, 9],
    'B': [10, 11, 12]
})
# 数据叠加
result = pd.concat([data1, data2], axis=0)  # 按行叠加
result_column = pd.concat([data1, data2], axis=1)  # 按列叠加
print("Row concat:", result)
print("Column concat:", result_column)
3. 数据兼并(Merge)

数据兼并是将两个或多个数据会集的某些列依照某种规矩(如求和、求平均等)兼并在一同。咱们可以运用pandas的groupby()和agg()函数进行数据兼并。

import pandas as pd
# 创立一个示例数据集
data = pd.DataFrame({
    'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
    'Value': [10, 20, 30, 40, 50, 60]
})
# 数据兼并
result = data.groupby('Category').agg({'Value': 'sum'})  # 按类别求和
print("Merge:", result)

结语

数据清洗是数据剖析的基石。经过本文的介绍,希望您可以更深化地了解数据清洗的重要性和办法,并在实践工作中运用这些常识,成为一名优异的数据剖析师。