python 对数据整理和预处理

自己复习用,内容大融合,还在编写中...

数据整理和预处理是数据分析和机器学习项目中一个至关重要的步骤。这一过程涉及到从原始数据中清洗、筛选和转换数据,以便于进行进一步的分析或建模。以下是一些常见的数据整理和预处理步骤:

  1. 数据清洗:

    • 移除重复或无关的记录。
    • 处理缺失值,可以通过删除含有缺失值的记录、填充缺失值或使用插值方法来处理。
    • 识别和修正错误的数据点或异常值。
  2. 数据转换:

    • 标准化归一化数据,以便于不同量级的特征可以被平等地考虑。
    • 进行数据编码,如将类别数据转换为数值数据,常见的方法包括独热编码(One-Hot Encoding)或标签编码(Label Encoding)。
    • 特征工程,包括创建新的特征或修改现有特征,以增强模型的预测能力。
  3. 数据分割:

    • 将数据集分割成训练集、验证集和测试集,以便于在不同的数据子集上训练和评估模型的性能。
  4. 数据探索:

    • 进行探索性数据分析(EDA),通过统计摘要、可视化等方法,理解数据的分布、趋势和关系。
  5. 特征选择:

    • 选择对预测目标最有用的特征,以减少模型的复杂性和过拟合的风险。这可以通过各种统计测试、模型基础的特征重要性评估等方法来实现。
  6. 处理不平衡数据:

    • 在分类问题中,如果某些类别的样本数量远多于其他类别,可能需要进行重采样技术,如过采样少数类别或欠采样多数类别,以避免模型偏向于预测多数类别。

目录 

数据清洗

1. 处理缺失值

2. 修正或删除异常值

识别异常值

1.统计方法

2.可视化方法

3.基于模型的方法

修正异常值

1.删除:

2.修正:

3.替换:

4.分箱:

5.变换:

3.处理重复数据

4.数据类型转换

5.数据列的重命名

6.索引重置

数据转换

1.标准化和归一化

Z-分数标准化

最小-最大归一化

2.数据编码

标签编码 

独热编码

二进制编码

频率编码

3.特征工程


数据清洗

在Python中进行数据清洗通常涉及多个步骤,包括处理缺失值、异常值、重复数据等。Pandas是Python中最流行的数据处理库之一,提供了丰富的数据结构和功能,非常适合进行数据清洗。以下是一些基本的数据清洗操作,使用Pandas来实现。

1. 处理缺失值

缺失值处理是数据清洗中的一项基本任务。常见的处理方法包括删除含有缺失值的行或列,或者填充缺失值。

import pandas as pd
import numpy as np


# 示例DataFrame
df = pd.DataFrame({
    'A': [1, 2, np.hi, 4],
    'B': [5, np.hi, np.hi, 8],
    'C': [10, 20, 30, 40]
})

# 删除含有缺失值的行
df_dropna = df.dropna()

# 填充缺失值,例如使用列的平均值
df_fillna = df.fillna(df.mean())

2. 修正或删除异常值

识别异常值

1.统计方法

  • Z-分数: 使用Z-分数(或标准分数)识别异常值是一种基于统计学的方法,它考虑了数据的均值和标准差。Z-分数表示一个数据点与数据集均值的差异,用标准差的数量表示。数据点的Z-分数越高,说明这个数据点与均值的差异越大。在实践中,通常认为Z-分数的绝对值大于2或3(根据具体情况而定)的数据点可能是异常值。

以下示例展示了如何使用Python的SciPy库计算Z-分数,并使用Pandas识别和过滤异常值。

import pandas as pd
from scipy import stats

# 创建示例数据
data = {'column_name': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100]}
df = pd.DataFrame(data)

# 计算Z-分数
df['Z_score'] = stats.zscore(df['column_name'])

# 过滤异常值,这里以Z-分数的绝对值大于3为标准
outliers = df[(df['Z_score'].abs() > 3)]
non_outliers = df[(df['Z_score'].abs() <= 3)]

print("异常值:\n", outliers)
print("\n非异常值:\n", non_outliers)

在这个例子中,stats.zscore()函数计算了column_name列的Z-分数。然后,基于Z-分数的绝对值大于3的规则,数据被分类为异常值或非异常值。

        注意事项

  • Z-分数方法假设数据大致符合正态分布。如果数据分布显著偏离正态分布,这种方法可能不太适用。
  • Z-分数的阈值(常用的是2或3)可以根据数据的具体情况进行调整。阈值越低,识别为异常的数据点越多。
  • 和处理IQR识别的异常值一样,识别出的异常值应该仔细检查,以确定它们是否真的是错误或者只是自然波动的结果。在某些情况下,异常值可能代表了重要的信息。

  • IQR(四分位距): IQR(Interquartile Range,四分位距)是统计学中用于衡量数据变异性和识别异常值的一种方法。它是上四分位数(Q3)与下四分位数(Q1)之间的差值,反映了数据集中间50%数据的分布范围。计算IQR可以帮助确定数据的离散度和异常值的存在。通常,低于Q1 - 1.5 x IQR或高于Q3+1.5 x IQR的数据点被视为异常值。

        计算步骤:

  • 排序:将数据从小到大排序。
  • 计算Q1和Q3
    • Q1(第一四分位数):是将数据分成四等份后,位于第一等份的最后一个数值,表示了所有数据中有25%的数据小于或等于这个值。
    • Q3(第三四分位数):同理,表示了所有数据中有75%的数据小于或等于这个值。
  • 计算IQR:IQR=Q3-Q1

在Python中,可以使用Pandas或NumPy库来方便地计算IQR。以下是一个使用Pandas的例子:

假设你有一个DataFrame df,其中包含你想要检查异常值的列 column_name

import pandas as pd

# 创建示例数据
data = {'column_name': [1, 2, 3, 4, 5, 6, 100, 7, 8, 9, 10]}
df = pd.DataFrame(data)

# 计算Q1和Q3
Q1 = df['column_name'].quantile(0.25)
Q3 = df['column_name'].quantile(0.75)

# 计算IQR
IQR = Q3 - Q1

# 定义异常值的范围
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# 识别异常值
outliers = df[(df['column_name'] < lower_bound) | (df['column_name'] > upper_bound)]
non_outliers = df[(df['column_name'] >= lower_bound) & (df['column_name'] <= upper_bound)]

print("异常值:\n", outliers)
print("\n非异常值:\n", non_outliers)

在这个例子中,quantile(0.25)quantile(0.75)分别用于计算第一四分位数(Q1)和第三四分位数(Q3),然后根据这些值计算IQR。接着,根据IQR定义异常值的界限:低于Q1 - 1.5 * IQR或高于Q3 + 1.5 * IQR的值被视为异常值。最后,使用这些界限过滤DataFrame以识别异常值和非异常值。

注意事项

  • 这种方法假设数据大致是对称分布的,如果数据严重偏斜,可能需要其他方法来更准确地识别异常值。
  • IQR方法适用于连续数据。对于分类数据,异常值的识别可能需要不同的方法。
  • 异常值不一定总是错误或不希望的数据点,有时候它们可能表示重要的、值得进一步研究的现象。因此,确定数据点是否真的是异常值,并决定如何处理它们之前,需要仔细考虑上下文。
2.可视化方法

箱形图(Boxplot): 利用IQR规则,箱形图直观地显示异常值。

箱形图(Boxplot)是一种标准的图表表示形式,用于显示数据的分布情况,包括中位数、四分位数以及异常值。它是通过数据的四分位数(Q1, Q3)和中位数(Q2)来构建的,同时利用这些四分位数计算IQR(四分位距),从而识别数据中的潜在异常值。在箱形图中,异常值通常是通过小圆点或星号之类的标记来展示,这些值落在四分位数之外的特定范围。

Python中的Matplotlib和Seaborn库都可以用来绘制箱形图。

使用matplotlib

import matplotlib.pyplot as plt
import numpy as np

# 创建示例数据
data = np.random.normal(0, 1, 100)
data_with_outliers = np.append(data, [2.5, 3.5, -3, -3.5])  # 添加一些异常值

# 绘制箱形图
plt.boxplot(data_with_outliers)
plt.title('Boxplot with Outliers')
plt.show()

绘制了一个包含异常值的箱形图。图中清晰地展示了数据的分布情况,包括中位数、四分位数以及标记为异常值的点。

散点图: 可以帮助直观识别出偏离数据集群体的数据点。

# 创建示例数据
x = np.random.normal(0, 1, 100)
y = np.random.normal(0, 1, 100)

# 添加一些异常值
x_with_outliers = np.append(x, [2.5, 3, -3, -2.5])
y_with_outliers = np.append(y, [2, -2, 3, -3])

# 绘制散点图
plt.figure(figsize=(8, 6))
plt.scatter(x_with_outliers, y_with_outliers)
plt.title('Scatter Plot with Outliers')
plt.xlabel('X axis')
plt.ylabel('Y axis')
plt.grid(True)
plt.show()

图中清楚地展示了大多数数据点围绕中心聚集,同时也直观地标识了偏离这个集群的异常值。这种图形是探索数据集分布和识别异常数据点的有效方式。

3.基于模型的方法

使用聚类算法(如DBSCAN)或异常检测算法(如孤立森林)来识别数据集中的异常值。我们可以使用Python的Scikit-learn库,它提供了这两种算法的实现。以下是使用这两种方法的示例:

使用DBSCAN识别异常值

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法,可以将密集区域的点划分为簇,并将稀疏区域的点标记为异常值或噪声点。

from sklearn.cluster import DBSCAN
import numpy as np

# 创建示例数据
X = np.random.rand(100, 2) * 100  # 生成一些随机数据

# 应用DBSCAN算法
dbscan = DBSCAN(eps=10, min_samples=5)
dbscan.fit(X)

# 标记异常值
outlier_mask = dbscan.labels_ == -1

# 获取异常值
outliers = X[outlier_mask]

# 显示异常值的数量
print(f"Identified outliers: {len(outliers)}")

使用孤立森林识别异常值

孤立森林(Isolation Forest)是一种高效的异常值检测算法,适用于高维数据。它通过随机选择特征并随机选择切分值来“孤立”观察值,异常值的“孤立”速度通常比正常值要快。

from sklearn.ensemble import IsolationForest
import numpy as np

# 创建示例数据
X = np.random.rand(100, 2) * 100  # 生成一些随机数据

# 应用孤立森林算法
iso_forest = IsolationForest(n_estimators=100, contamination='auto')
iso_forest.fit(X)

# 预测数据点是正常值还是异常值
scores = iso_forest.decision_function(X)
outliers = X[scores < 0]

# 显示异常值的数量
print(f"Identified outliers: {len(outliers)}")

在实际应用中,你需要根据数据的具体特点选择合适的参数,如DBSCAN的epsmin_samples,孤立森林的n_estimatorscontamination等,以达到最佳的异常值检测效果。

修正异常值

1.删除:

如果异常值的数量不多,且可以合理假设它们是由错误或异常情况引起的,可以直接删除这些数据点。

# 假设outliers是异常值的索引
clean_data = X[~outlier_mask]

在Python中,clean_data = X[~outlier_mask] 这行代码的作用是从数据集 X 中过滤掉被标记为异常值的数据点,以便仅保留非异常(或"干净")的数据点。这里,X 代表原始数据集,通常是一个二维数组或类似结构,而 outlier_mask 是一个布尔数组(或布尔型的索引数组),其中 True 表示对应位置的数据点是异常值,False 表示数据点是正常的。

~ 符号是Python中的按位取反操作符,用于布尔数组时,它会将 True 转换为 False,将 False 转换为 True。因此,~outlier_mask 会得到一个与 outlier_mask 相反的布尔数组,即原来标记为异常值(True)的位置现在变为 False,原来标记为正常的数据点(False)现在变为 True

将这个取反后的布尔数组用作 X 的索引,X[~outlier_mask] 实际上是选择了所有未被标记为异常的数据点,从而实现了从原始数据集中删除异常值的目的。这样,clean_data 就包含了去除了异常值之后的数据集,可以用于后续的数据分析或机器学习建模过程。

2.修正:

如果可以确定异常值是由于数据录入错误等原因造成的,可以尝试修正这些值到合理范围内。

# 假设已知正确的范围,修正异常值
X[outlier_mask] = np.random.rand(np.sum(outlier_mask), 2) * 100  # 示例:用随机值替换

np.random.rand(np.sum(outlier_mask), 2) * 100 生成了一个新的随机数组,其形状由 outlier_maskTrue 的数量决定(即异常值的数量),和 X 中每个数据点的维度(在这个例子中是2)。这个随机数组的值在0到1之间,乘以100后,其范围变为0到100。

X[outlier_mask] = ...X 中所有被标记为异常的数据点替换为上述生成的随机数值。这意味着原来的异常值会被这些新生成的随机数值覆盖。

3.替换:

使用中位数、平均值或其他代表性数据替换异常值,特别是在处理少量异常值时,这种方法可以保持数据集的整体分布特性。对于连续数据,可以使用插值方法来估计异常值的合理值。

# 使用中位数替换异常值
median_values = np.median(X, axis=0)
for index in np.where(outlier_mask)[0]:
    X[index] = median_values
4.分箱:

将连续数据离散化,通过创建分箱(bins)来减少异常值的影响。

分箱(Binning)或桶装(Bucketing)是数据预处理中的一种技术,旨在将连续变量分割成多个区间或“箱子”(Buckets)。每个箱子代表了一个值范围,连续变量中的值根据其所在的范围被分配到相应的箱子中。分箱可以减少连续数据的小变动和噪声的影响,并且能够简化模型的复杂度。这种方法在数据分析、机器学习以及数据可视化中被广泛应用。

分箱主要有以下几种类型:

  1. 等宽分箱(Equal-width binning):这种方法将数据的整个范围分割成宽度相等的区间。例如,将年龄分为0-20、21-40、41-60和61-80这样的区间。等宽分箱容易实现,但可能会因为数据分布不均匀而导致某些箱子中的数据点过多或过少。

  2. 等深分箱(Equal-depth binning)或等频分箱(Equal-frequency binning):在这种方法中,每个箱子包含大致相同数量的数据点。这有助于避免某些箱子过满而其他箱子过空的问题,但箱子的宽度可能会不同。

  3. 基于聚类的分箱:使用聚类算法(如K-均值聚类)将数据点分组成不同的箱子。这种方法可以根据数据的自然聚类将其分箱,可能更能反映数据的内在结构。

分箱的目的和优势包括:

  • 减少噪声:通过将连续数据值归入较大的“桶”中,可以减少数据的小波动。
  • 处理异常值:分箱可以将异常值归入特定的箱子中,从而降低它们对分析结果的影响。
  • 提升模型的稳健性:分箱后的数据对异常值不那么敏感,有助于提高模型的稳健性。
  • 简化模型:通过将连续变量转换为类别变量,分箱可以简化模型的复杂度,使模型更易于理解和解释。

在实际应用中,分箱的方法和参数选择需根据具体的数据特性和分析目标来确定。

# 将数据分为10个等宽箱
bins = np.linspace(np.min(X), np.max(X), 11)
digitized = np.digitize(X, bins)

np.linspace(start, stop, num) 生成一个线性等间隔的向量。这个向量从 start 开始,到 stop 结束,总共包含 num 个值。在这个例子中,startX 中的最小值(np.min(X)),stopX 中的最大值(np.max(X)),num 是11。因此,这行代码的作用是生成一个包含11个线性等间隔数值的数组,这些数值作为分箱的边界,将 X 的值范围分成10个等宽的箱子

np.digitize(x, bins) 函数返回输入数组 x 中的每个值相对于 bins 数组中的箱子的索引。这里的 x 是数据数组 X,而 bins 是上一步计算得到的箱子边界数组。对于 X 中的每个值,np.digitize 确定它属于哪个箱子,并返回该箱子的索引。结果数组 digitized 的大小与 X 相同,其中包含的是每个数据点对应的箱子索引。

这个过程可以用来离散化连续变量,将连续的数值转换为有限数量的离散类别。这对于一些特定的数据分析和机器学习算法很有用,因为它可以简化数据结构,减少模型对数据细微差别的敏感度,并有助于处理异常值和噪声

5.变换:

对数据进行变换(如对数变换、平方根变换等),以减少异常值的影响,特别是对偏斜分布的数据

# 对数变换
X_transformed1 = np.log(X + 1 - np.min(X))  # 避免负值
# 平方根变换
X_transformed2 = np.sqrt(X - np.min(X))

3.处理重复数据

重复数据可能会导致数据分析的不准确,因此需要被识别和删除。

# 查找重复行
duplicates = df[df.duplicated()]

# 删除重复行
df_unique = df.drop_duplicates()

df.duplicated() 返回一个布尔序列,标记DataFrame df 中的每一行是否为重复行。默认情况下,它将第一次出现的行视为唯一,之后相同的行被视为重复。

df[df.duplicated()] 根据 df.duplicated() 返回的布尔序列选择数据,即选择所有被标记为重复的行。结果 duplicates 是一个DataFrame,包含了 df 中所有的重复行。

df.drop_duplicates() 返回一个新的DataFrame,其中删除了 df 中的重复行。默认情况下,它保留每组重复行中的第一行,删除其余的重复行。

结果 df_unique 是一个去除了所有重复行后的DataFrame

通过这两行代码,你可以先识别DataFrame中的重复行,然后创建一个新的DataFrame副本,其中不包含任何重复行。这在数据清洗和预处理阶段是非常常见的操作,可以帮助确保数据的唯一性和一致性,避免因数据重复而导致的分析误差。

4.数据类型转换

# 将列转换为特定数据类型
df['A'] = df['A'].astype(float)

这行Python代码使用Pandas库将DataFrame df 中的列 'A' 的数据类型转换为浮点数(float)。详细解释如下:

  • df['A']: 这部分选取了DataFrame df 中名为 'A' 的列。

  • .astype(float): astype() 方法用于转换Pandas对象中的数据类型。在这个例子中,它被用来将列 'A' 的数据类型转换为 float 类型,即浮点数类型。

  • df['A'] = ...: 最后,将转换后的数据重新赋值给原来的列 'A',这样列 'A' 中原来的数据就被转换为了浮点数类型。

这种类型转换操作在数据预处理阶段非常常见,尤其是在处理来自不同来源的数据时,因为原始数据可能包含错误的数据类型(例如,数值被误存为文本字符串)。将数据转换为正确的类型是进行进一步分析、可视化或机器学习建模的重要步骤。

5.数据列的重命名

为了提高数据的可读性,有时候需要重命名DataFrame中的列。

# 重命名列
df.rename(columns={'A': 'new_name_A', 'B': 'new_name_B'}, inplace=True)

6.索引重置

在删除行或列后,可能需要重置DataFrame的索引

df_reset = df.reset_index(drop=True)

这行Python代码使用Pandas库的 reset_index() 方法来重置DataFrame df 的索引。详细解释如下:

  • df.reset_index(): 这个方法将DataFrame df 的索引重置为默认整数索引。原来的索引会变成DataFrame的一个列,除非另有指定。

  • drop=True: 这个参数告诉reset_index()方法不要将旧的索引添加到DataFrame的列中,而是完全舍弃它。如果不设置drop=True,原来的索引会成为一个新的列。

  • df_reset = ...: 方法的结果(即索引被重置的DataFrame)被赋值给变量df_reset。这样,df_reset包含了和原始df相同的数据,但索引被重置为从0开始的连续整数。

重置索引常用于数据处理过程中,特别是在删除数据行或进行过滤之后,原始的索引可能会变得不连续。重置索引可以使DataFrame的索引恢复连续,便于后续操作和分析。drop=True参数尤其有用,因为在很多情况下,保留旧索引并不是必需的,而且可能会引起混淆。

数据转换

在Python中进行数据转换是数据预处理的一个重要步骤,可以帮助提高模型训练的效果和数据分析的准确性。这里介绍几种常见的数据转换方法:

1.标准化和归一化

这两种方法通常用于调整数值型数据的尺度。

数据标准化是数据预处理的一个重要步骤,旨在将来自不同范围的特征转换到同一尺度。标准化通常对算法性能有正面影响,特别是对于基于距离的算法(如K-最近邻、K-均值聚类)和梯度下降优化的算法(如线性回归、逻辑回归、神经网络)。标准化数据可以加快训练过程并提高模型的性能。

常见标准化方法

以下是使用Python进行数据标准化的一些示例,利用Pandas进行数据处理和Scikit-learn库中的StandardScalerMinMaxScaler

Z-分数标准化
from sklearn.preprocessing import StandardScaler
import pandas as pd

# 假设df是一个Pandas DataFrame,包含你想要标准化的数据列

scaler = StandardScaler()
df_scaled = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)

这段Python代码使用了Scikit-learn库中的StandardScaler类来对一个Pandas DataFrame df进行标准化处理,然后将处理后的数据转换回一个新的DataFrame df_scaled。具体步骤和意义如下:

  1. 初始化StandardScaler

    scaler = StandardScaler() 创建了一个StandardScaler对象。StandardScaler用于将每个特征(即DataFrame中的每列)标准化,使其具有平均值为0和标准差为1。这是通过减去特征的均值并除以其标准差来实现的。
  2. 拟合并转换数据

    scaler.fit_transform(df)df进行两个操作:首先,fit方法计算了df中每个特征的均值和标准差。然后,transform方法使用这些均值和标准差将每个特征转换为标准化的形式。这样,每个特征的均值变为0,标准差变为1。
  3. 转换回DataFrame

    pd.DataFrame(scaler.fit_transform(df), columns=df.columns)fit_transform方法返回的NumPy数组转换回一个Pandas DataFrame。为了保持与原始df相同的列名,columns=df.columns用于指定新DataFrame的列名。

这个过程的目的是使数据更适合于使用线性模型等机器学习算法,因为很多算法都假设数据各特征都是以0为中心且具有相同的单位方差。标准化是数据预处理中常用的技术之一,有助于提高算法的收敛速度和模型

最小-最大归一化
from sklearn.preprocessing import MinMaxScaler
import pandas as pd

# 同样假设df是一个包含你想要标准化的数据列的DataFrame

min_max_scaler = MinMaxScaler()
df_min_max_scaled = pd.DataFrame(min_max_scaler.fit_transform(df), columns=df.columns)

2.数据编码

在处理数据时,尤其是在准备数据以供机器学习模型使用时,对特征进行编码是一项常见且关键的步骤。这主要是因为许多机器学习算法预期输入是数值型的,而不是类别型(字符串)或者混合类型的数据。以下是几种常用的数据编码方法:

标签编码

标签编码将每个类别映射到一个唯一的整数。这种方法适用于类别之间存在某种顺序(例如“低”,“中”,“高”)的情况。

from sklearn.preprocessing import LabelEncoder

# 初始化标签编码器
label_encoder = LabelEncoder()

# 假设df['category']是需要编码的类别特征
df['category_encoded'] = label_encoder.fit_transform(df['category'])

这段Python代码使用了Scikit-learn库中的LabelEncoder类来对DataFrame df中名为'category'的列进行标签编码。具体步骤和意义如下:

  1. 初始化LabelEncoder

    label_encoder = LabelEncoder() 创建了一个LabelEncoder对象。这个对象能够将类别型的标签转换为从0到n_classes-1的整数,其中n_classes是不同标签的数量。
  2. 对类别特征进行编码

    label_encoder.fit_transform(df['category']) 这个方法首先对df['category']列中的所有唯一标签进行拟合(fit),即学习每个标签与一个整数之间的映射关系。然后,它将这些标签转换(transform)为对应的整数。
  3. 保存编码结果

    df['category_encoded'] = ...fit_transform方法返回的整数数组赋值给df中的新列'category_encoded'。这样,原始的类别标签就被转换为了整数形式,并保存在了新的列中。

通过这种方式,原始的文本类别特征被转换为了模型可以处理的数值型特征。这对于大多数机器学习算法是必需的,因为它们通常只能处理数值型输入。标签编码特别适用于类别特征的取值较少且不存在明显序列关系时(尽管它实际上引入了一个序列,这可能会影响某些模型,特别是线性模型和基于距离的模型)。

独热编码

独热编码为每个类别创建一个新的二进制列,对于每个数据点,类别对应的列为1,其他列为0。这种方法适用于类别之间没有顺序的情况。

from sklearn.preprocessing import OneHotEncoder

# 初始化独热编码器
onehot_encoder = OneHotEncoder(sparse=False)

# 假设df['category']是需要编码的类别特征,需要先将其转换为列向量
category_encoded = onehot_encoder.fit_transform(df[['category']])

# 将编码结果转换回DataFrame
df_onehot = pd.DataFrame(category_encoded, columns=onehot_encoder.get_feature_names_out())

这段代码使用了Scikit-learn库的OneHotEncoder类来对DataFrame df中的'category'列进行独热编码(One-Hot Encoding)。下面逐步解释这段代码的含义和作用:

初始化OneHotEncoder:

  • onehot_encoder = OneHotEncoder(sparse=False) 创建了一个OneHotEncoder对象。参数sparse=False指定返回的数组是密集型的ndarray,而不是稀疏矩阵。这样做便于后续操作,特别是当需要将独热编码结果转换回Pandas DataFrame时。

对类别特征进行独热编码:

  • category_encoded = onehot_encoder.fit_transform(df[['category']]) 这行代码执行两个步骤:
    1. fit步骤学习'category'列中所有唯一类别的名称。
    2. transform步骤根据这些类别名称为每个类别生成一个独热编码的二进制列,每个观测的类别在相应的列中标记为1,其余列为0。
    注意,df[['category']]是将'category'列作为DataFrame传递给fit_transform方法,这是因为OneHotEncoder期望二维输入。

将编码结果转换回DataFrame:

  • df_onehot = pd.DataFrame(category_encoded, columns=onehot_encoder.get_feature_names_out()) 这行代码创建了一个新的DataFrame,其内容是独热编码后的数据,列名是由OneHotEncoder自动生成的,反映了原始类别特征的每个唯一值。

    • category_encoded是独热编码后的数据数组。
    • columns=onehot_encoder.get_feature_names_out()OneHotEncoder获取编码后的特征名称,用作新DataFrame的列名。这些名称通常是原始类别名称的派生,能够清楚地表示每个列对应的原始类别值。

通过这种方式,原始的类别特征被转换为了模型可以直接处理的形式,特别是对于那些要求输入特征为数值型且不假定类别之间有序关系的模型(如大多数线性模型、神经网络等)。独热编码后,每个类别都被表示为一个长度等于类别数量的二进制向量,保证了模型不会错误地解释类别之间的数值关系。

二进制编码

二进制编码首先将类别编码为整数,然后将整数转换为二进制,最后将二进制拆分为各个位,每个位作为一个特征。这种方法相比独热编码,可以减少维度的数量。

import category_encoders as ce

# 初始化二进制编码器
binary_encoder = ce.BinaryEncoder(cols=['category'])

# 对数据进行二进制编码
df_binary_encoded = binary_encoder.fit_transform(df['category'])

频率编码

频率编码将类别替换为它们出现的频率。这种方法适用于类别的重要性与其出现频率相关的情况。

frequency_map = df['category'].value_counts().to_dict()
df['category_encoded'] = df['category'].map(frequency_map)

这段Python代码使用Pandas库对DataFrame df中的'category'列进行频率编码。具体来说,它通过以下步骤实现:

计算每个类别的频率:

  • frequency_map = df['category'].value_counts().to_dict() 首先使用value_counts()方法计算'category'列中每个类别出现的次数,然后调用to_dict()将这些计数转换为一个字典。字典的键是类别,值是相应类别出现的次数。

应用频率编码:

  • df['category_encoded'] = df['category'].map(frequency_map) 然后使用map()方法将上一步得到的频率映射(frequency_map)应用到每个类别上。map()方法根据frequency_map字典中提供的映射关系,将'category'列中的每个类别值替换为其出现频率。

这样,原始的类别特征'category'被转换为了一个新的数值特征'category_encoded',其中的值不再是类别本身,而是表示该类别在数据集中出现频率的数值。这种转换有几个潜在的好处:

  • 降维:对于拥有大量类别的特征,频率编码可以有效地减少模型需要处理的特征数量,因为它不会像独热编码那样为每个类别创建一个新的列。
  • 保留信息:通过编码为出现频率,模型可以捕捉到类别出现频率的信息,这在某些情况下可能对预测有帮助。
  • 简化模型:由于转换后的特征是数值型的,可以直接用于大多数机器学习模型,而不需要进一步的复杂转换。

然而,需要注意的是,这种编码方式可能会导致不同的类别被赋予相同的编码(如果它们的出现频率相同),从而丢失一些类别间的区分度。因此,在使用频率编码时,应当根据具体的数据和任务需求仔细考虑。

3.特征工程

特征工程是机器学习中的一个重要环节,它涉及到创建新的特征或修改现有特征,目的是增强模型的预测能力。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值