全部版块 我的主页
论坛 新商科论坛 四区(原工商管理论坛) 商学院 创新与战略管理
43 0
2025-11-21

1. 数据预处理核心逻辑解析

以下为数据预处理阶段的核心函数实现,主要用于完成缺失值填充与类别字段的结构化解析:

# ========== 1) 预处理 ==========
def prepare_mercari_basic(df: pd.DataFrame,
category_col: str = "category_name",
brand_fill: str = "No Brand",
desc_fill: str = "No description",
cat_fill: str = "Unknown",
keep_original_category: bool = True) -> pd.DataFrame:
    """
    1) 填充 brand_name / item_description
    2) 安全拆分 category_name -> cat1/cat2/cat3(兼容缺失/层级不全/过多)
    """
    df = df.copy()
    if "brand_name" in df.columns:
        df["brand_name"] = df["brand_name"].fillna(brand_fill)
    if "item_description" in df.columns:
        df["item_description"] = df["item_description"].fillna(desc_fill)
    if category_col in df.columns:
        cats = (
            df[category_col]
            .fillna("")
            .str.extract(r"([^/]*)(?:/([^/]*))?(?:/(.*))?")
            .rename(columns={0: "cat1", 1: "cat2", 2: "cat3"})
        )
        cats = cats.replace("", np.nan).fillna(cat_fill)
        if not keep_original_category:
            df = df.drop(columns=[category_col])
        df = pd.concat([df, cats], axis=1)
    return df

def shrink_brands_for_ohe(df: pd.DataFrame, col: str = "brand_name", top_n: int = 4000) -> pd.DataFrame:
    """保留高频品牌,其余归为 'Other',降低 OHE 维度"""
    df = df.copy()
    if col not in df.columns:
        return df
    top = df[col].value_counts().nlargest(top_n).index
    df[col] = np.where(df[col].isin(top), df[col], "Other")
    return df
[此处为图片1]

2. 缺失值处理策略

根据前期分析,数据集中主要存在两类关键字段的缺失情况:品牌名称(brand_name)和商品描述(item_description)。针对这两类缺失,采用统一且明确的填充方式,避免引入噪声或偏差。

具体做法是使用语义清晰的占位符进行补全:

  • 当品牌信息缺失时,统一标记为“No Brand”;
  • 当商品描述为空时,则填充为“No description”。

相关代码如下所示:

if "brand_name" in df.columns:
    df["brand_name"] = df["brand_name"].fillna(brand_fill) # No Brand
if "item_description" in df.columns:
    df["item_description"] = df["item_description"].fillna(desc_fill) # No Description

3. 类别字段的结构化拆分

原始数据中的类别字段(如 category_name)以斜杠分隔的形式呈现,格式为:

Cat 1/Cat 2/Cat 3

然而该字段存在严重的不规则性:部分样本可能仅有两层分类(如 Cat 1/Cat 2),而另一些样本则可能包含四层甚至更多(如 Cat 1/Cat 2/Cat 3/Cat 4)。这种层级深度不一的情况给后续建模带来挑战。

为此,采取简化策略——仅提取前三级分类,并将所有超出第三级的内容合并至第三级。通过正则表达式实现安全拆分:

if category_col in df.columns:
    cats = (
        df[category_col]
        .fillna("")
        .str.extract(r"([^/]*)(?:/([^/]*))?(?:/(.*))?")
        .rename(columns={0: "cat1", 1: "cat2", 2: "cat3"})
    )
    cats = cats.replace("", np.nan).fillna(cat_fill)

上述逻辑首先将空值替换为空字符串,随后利用正则匹配提取最多三个层级。若原始字符串少于三层,则对应位置置为 NaN 并最终填充为“Unknown”;若超过三层,则第三段捕获从第三个斜杠开始的所有内容,确保信息不丢失。

最后,新生成的三个分类字段(cat1、cat2、cat3)被合并回原数据集。若参数 keep_original_category 设为 False,则原始的 category_name 字段将被移除,以减少冗余。

4. 品牌归并处理

这一操作的核心逻辑较为直观。由于 Mercari 是一个综合性的二手商品交易平台,支持各类商品的上架交易(类似于国内的闲鱼),因此商品所涉及的品牌种类极为繁杂。在这些品牌中,部分属于高频出现的品牌,而另一些则极少被提及。当品牌类别数量过于庞大时,若直接进行独热编码(One-Hot Encoding),将导致特征维度急剧膨胀,给后续建模带来计算负担和过拟合风险。

为解决该问题,我们设定一个阈值,仅保留出现频率最高的前 N 个品牌,其余所有低频品牌统一归入“Other”类别。这种处理方式有效控制了特征空间的规模,同时保留了主要品牌的信息价值。

[此处为图片1]

完成上述步骤后,整个数据预处理流程即告一段落。尽管该数据集本身的字段数量不多,处理过程相对简洁,但已为后续工作打下坚实基础。接下来的文章中,我们将正式进入关键环节——特征工程的构建与优化。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群