【Python10年经验总结】第三课 电商平台销售数据分析实践分解 – 数据转换(Data Transformation)
常见用的数据转换分类:
- 提取日期中的年、月、周、星期几
- 将字符串分类变量编码为哑变量(One-Hot Encoding)
- 计算订单总金额(单价×数量)
- 计算折扣率(实际支付价 / 原价)
- 构造用户购买频次特征
- 转换时间戳为可排序的时间序列
- 构造商品销量排名字段
- 合并多个数据源生成宽表
- 对价格进行标准化(Z-score)
- 构造是否参与促销的布尔标签
我们将展示如何进行这些常见的数据转换任务。假设我们有一个包含销售订单数据的DataFrame,并逐步应用这些转换操作。
首先,让我们创建一个示例DataFrame来模拟原始数据:
import pandas as pd
import numpy as np
# 创建示例DataFrame
data = {
'order_id': [1, 2, 3, 4, 5, 6, 7, 8],
'product_id': ['A001', 'B002', 'D004', 'E005', 'F006', 'G007', 'H008', 'I009'],
'category_code': ['C1', 'C2', 'C1', 'C3', 'C4', 'C5', 'C6', 'C7'],
'amount': [100.00, 200.00, 300.00, 400.00, 500.00, 600.00, 700.00, 800.00],
'original_price': [120.00, 220.00, 320.00, 420.00, 520.00, 620.00, 720.00, 820.00],
'quantity': [1, 2, 1, 1, 2, 1, 1, 2],
'order_date': ['2025-06-01', '2025-06-02', '2025-06-03', '2025-06-04', '2025-06-05', '2025-06-06', '2025-06-07', '2025-06-08'],
'customer_id': [101, 102, 103, 104, 105, 106, 107, 108],
'promotion': [False, True, False, True, False, True, False, True]
}
df = pd.DataFrame(data)
print("原始数据:")
print(df)
接下来,我们将逐个处理上述提到的数据转换任务。
1. 提取日期中的年、月、周、星期几
# 转换order_date为日期格式
df['order_date'] = pd.to_datetime(df['order_date'])
# 提取年、月、周、星期几
df['year'] = df['order_date'].dt.year
df['month'] = df['order_date'].dt.month
df['week_of_year'] = df['order_date'].dt.isocalendar().week.astype(int)
df['day_of_week'] = df['order_date'].dt.dayofweek
print("\n提取日期中的年、月、周、星期几后:")
print(df)
2. 将字符串分类变量编码为哑变量(One-Hot Encoding)
# 将category_code进行one-hot encoding
df_encoded = pd.get_dummies(df, columns=['category_code'], prefix='cat')
print("\n将字符串分类变量编码为哑变量后:")
print(df_encoded)
3. 计算订单总金额(单价×数量)
# 计算订单总金额
df_encoded['total_amount'] = df_encoded['amount'] * df_encoded['quantity']
print("\n计算订单总金额后:")
print(df_encoded)
4. 计算折扣率(实际支付价 / 原价)
# 计算折扣率
df_encoded['discount_rate'] = (df_encoded['amount'] / df_encoded['original_price']).round(2)
print("\n计算折扣率后:")
print(df_encoded)
5. 构造用户购买频次特征
假设我们有一个客户购买记录的DataFrame,用于构造用户购买频次特征。
# 创建客户购买记录的DataFrame
purchase_history = {
'customer_id': [101, 102, 103, 104, 105, 106, 107, 108, 101, 102, 103, 104],
'purchase_count': [2, 3, 1, 2, 1, 3, 2, 1, 1, 2, 1, 3]
}
df_purchase_history = pd.DataFrame(purchase_history)
# 合并客户购买记录
df_transformed = pd.merge(df_encoded, df_purchase_history, on='customer_id', how='left')
print("\n构造用户购买频次特征后:")
print(df_transformed)
6. 转换时间戳为可排序的时间序列
在我们的例子中,order_date已经是日期时间格式,可以直接排序。
# 确保order_date是datetime类型
df_transformed['order_date'] = pd.to_datetime(df_transformed['order_date'])
# 按order_date排序
df_sorted = df_transformed.sort_values(by='order_date')
print("\n按order_date排序后:")
print(df_sorted)
7. 构造商品销量排名字段
假设我们有一个商品销量统计的DataFrame,用于构造商品销量排名特征。
# 创建商品销量统计的DataFrame
product_sales = {
'product_id': ['A001', 'B002', 'D004', 'E005', 'F006', 'G007', 'H008', 'I009'],
'sales_rank': [1, 2, 3, 4, 5, 6, 7, 8]
}
df_product_sales = pd.DataFrame(product_sales)
# 合并商品销量统计
df_final = pd.merge(df_sorted, df_product_sales, on='product_id', how='left')
print("\n构造商品销量排名字段后:")
print(df_final)
8. 对价格进行标准化(Z-score)
from scipy.stats import zscore
# 对amount列进行z-score标准化
df_final['amount_zscore'] = zscore(df_final['amount'])
print("\n对价格进行标准化后:")
print(df_final)
9. 构造是否参与促销的布尔标签
# 构造是否参与促销的布尔标签
df_final['is_promotion'] = df_final['promotion'].astype(bool)
print("\n构造是否参与促销的布尔标签后:")
print(df_final)
综合以上步骤,最终的转换后的DataFrame如下:
这段代码展示了从原始数据到经过全面转换的数据的过程。你可以根据实际需求调整每一步的操作。
import pandas as pd
import numpy as np
from scipy.stats import zscore
# 创建示例DataFrame
data = {
'order_id': [1, 2, 3, 4, 5, 6, 7, 8],
'product_id': ['A001', 'B002', 'D004', 'E005', 'F006', 'G007', 'H008', 'I009'],
'category_code': ['C1', 'C2', 'C1', 'C3', 'C4', 'C5', 'C6', 'C7'],
'amount': [100.00, 200.00, 300.00, 400.00, 500.00, 600.00, 700.00, 800.00],
'original_price': [120.00, 220.00, 320.00, 420.00, 520.00, 620.00, 720.00, 820.00],
'quantity': [1, 2, 1, 1, 2, 1, 1, 2],
'order_date': ['2025-06-01', '2025-06-02', '2025-06-03', '2025-06-04', '2025-06-05', '2025-06-06', '2025-06-07', '2025-06-08'],
'customer_id': [101, 102, 103, 104, 105, 106, 107, 108],
'promotion': [False, True, False, True, False, True, False, True]
}
df = pd.DataFrame(data)
# 转换order_date为日期格式
df['order_date'] = pd.to_datetime(df['order_date'])
# 提取年、月、周、星期几
df['year'] = df['order_date'].dt.year
df['month'] = df['order_date'].dt.month
df['week_of_year'] = df['order_date'].dt.isocalendar().week.astype(int)
df['day_of_week'] = df['order_date'].dt.dayofweek
# 将category_code进行one-hot encoding
df_encoded = pd.get_dummies(df, columns=['category_code'], prefix='cat')
# 计算订单总金额
df_encoded['total_amount'] = df_encoded['amount'] * df_encoded['quantity']
# 计算折扣率
df_encoded['discount_rate'] = (df_encoded['amount'] / df_encoded['original_price']).round(2)
# 创建客户购买记录的DataFrame
purchase_history = {
'customer_id': [101, 102, 103, 104, 105, 106, 107, 108, 101, 102, 103, 104],
'purchase_count': [2, 3, 1, 2, 1, 3, 2, 1, 1, 2, 1, 3]
}
df_purchase_history = pd.DataFrame(purchase_history)
# 合并客户购买记录
df_transformed = pd.merge(df_encoded, df_purchase_history, on='customer_id', how='left')
# 确保order_date是datetime类型
df_transformed['order_date'] = pd.to_datetime(df_transformed['order_date'])
# 按order_date排序
df_sorted = df_transformed.sort_values(by='order_date')
# 创建商品销量统计的DataFrame
product_sales = {
'product_id': ['A001', 'B002', 'D004', 'E005', 'F006', 'G007', 'H008', 'I009'],
'sales_rank': [1, 2, 3, 4, 5, 6, 7, 8]
}
df_product_sales = pd.DataFrame(product_sales)
# 合并商品销量统计
df_final = pd.merge(df_sorted, df_product_sales, on='product_id', how='left')
# 对amount列进行z-score标准化
df_final['amount_zscore'] = zscore(df_final['amount'])
# 构造是否参与促销的布尔标签
df_final['is_promotion'] = df_final['promotion'].astype(bool)
print("最终转换后的数据:")
print(df_final)