生成二值特征矩阵:使用Pandas crosstab与reindex的高效方法

花韻仙語
发布: 2025-09-29 22:26:02
原创
906人浏览过

生成二值特征矩阵:使用Pandas crosstab与reindex的高效方法

本教程旨在详细阐述如何将具有事务性记录(如用户-特征对)的原始数据转换为一个二值化的特征矩阵。我们将重点介绍如何利用Pandas库中的crosstab函数进行数据透视,并结合reindex方法确保所有指定用户都包含在输出中,同时为未使用的特征填充零值,从而高效、清晰地构建用户-特征关联矩阵。

1. 问题背景与目标

在数据分析和机器学习领域,我们经常需要将用户的行为日志或事务数据转换为结构化的特征矩阵。例如,给定一个包含用户 (personnumber) 及其使用的特征 (featuresk) 的数据集,目标是创建一个新的dataframe,其中:

  • 行代表特定的用户列表。
  • 列代表所有唯一的特征。
  • 单元格的值为1,如果该用户使用了该特征;为0,如果该用户未曾使用该特征。

原始数据可能如下所示:

featureSk PersonNumber
A 1001
B 1001
C 1003
C 1004
A 1002
B 1005

我们希望为指定的 PersonNumber 列表(例如 [1001, 1002, 1003])生成如下的二值特征矩阵:

PersonNumber A B C
1001 1 1 0
1002 1 0 0
1003 0 0 1

直接通过循环或条件判断来构建这样的矩阵效率低下且代码复杂,尤其是在处理大规模数据时。

2. 使用 pd.crosstab 构建基础频率矩阵

Pandas库提供了一个强大的函数 pd.crosstab,它能够根据两个或多个因子计算交叉表(频率表)。这正是我们解决问题的第一步:统计每个用户使用每个特征的次数。

pd.crosstab 的基本用法是 pd.crosstab(index, columns),其中 index 参数指定作为行索引的列,columns 参数指定作为列标题的列。

import pandas as pd

# 示例数据
data = {
    'featureSk': ['A', 'B', 'C', 'C', 'A', 'B'],
    'PersonNumber': [1001, 1001, 1003, 1004, 1002, 1005]
}
productusage_df = pd.DataFrame(data)

# 使用crosstab生成频率表
# index指定行,columns指定列
feature_matrix = pd.crosstab(productusage_df["PersonNumber"], productusage_df["featureSk"])

print("原始crosstab结果:")
print(feature_matrix)
登录后复制

输出结果:

原始crosstab结果:
featureSk     A  B  C
PersonNumber         
1001          1  1  0
1002          1  0  0
1003          0  0  1
1004          0  0  1
1005          0  1  0
登录后复制

pd.crosstab 默认会计算频率(即出现次数)。对于我们的二值化需求,任何大于0的计数都意味着该用户使用了该特征,可以视为1。幸运的是,crosstab 的输出已经满足了“0”表示未使用的需求。

3. 整合目标用户列表并处理缺失值

pd.crosstab 生成的矩阵只包含 productusage_df 中实际存在的 PersonNumber。如果我们的目标用户列表 vals 包含一些未在 productusage_df 中出现的用户,或者我们需要按照特定顺序排列用户,crosstab 的输出将不完整。

乾坤圈新媒体矩阵管家
乾坤圈新媒体矩阵管家

新媒体账号、门店矩阵智能管理系统

乾坤圈新媒体矩阵管家 17
查看详情 乾坤圈新媒体矩阵管家

为了解决这个问题,我们可以使用DataFrame的 reindex 方法。reindex 允许我们根据一个新的索引来对DataFrame进行重排。如果新索引中的某个值在原DataFrame中不存在,reindex 会默认添加该行/列并用 NaN 填充。通过设置 fill_value=0,我们可以将这些 NaN 值替换为0,这正是我们二值化需求所期望的。

# 目标用户列表
target_person_numbers = [1001, 1002, 1003]

# 使用reindex来包含所有目标用户,并用0填充缺失值
final_feature_matrix = feature_matrix.reindex(target_person_numbers, fill_value=0)

print("\n最终二值特征矩阵:")
print(final_feature_matrix)
登录后复制

输出结果:

最终二值特征矩阵:
featureSk     A  B  C
PersonNumber         
1001          1  1  0
1002          1  0  0
1003          0  0  1
登录后复制

通过这两步,我们成功地将原始的事务性数据转换成了所需的二值特征矩阵,并且确保了所有目标用户都被包含在内,未使用的特征被正确地标记为0。

4. 完整示例代码

以下是整合上述步骤的完整Python函数示例:

import pandas as pd

def generate_binary_feature_matrix(productusage_df: pd.DataFrame, target_person_numbers: list) -> pd.DataFrame:
    """
    根据产品使用日志生成一个二值化的用户-特征矩阵。

    Args:
        productusage_df (pd.DataFrame): 包含 'featureSk' 和 'PersonNumber' 列的DataFrame。
        target_person_numbers (list): 期望在输出矩阵中包含的PersonNumber列表。

    Returns:
        pd.DataFrame: 二值化的特征矩阵,其中行是PersonNumber,列是featureSk,
                      单元格值为1表示用户使用了该特征,0表示未使用的特征。
    """
    if not isinstance(productusage_df, pd.DataFrame):
        raise TypeError("productusage_df 必须是一个 Pandas DataFrame。")
    if 'featureSk' not in productusage_df.columns or 'PersonNumber' not in productusage_df.columns:
        raise ValueError("productusage_df 必须包含 'featureSk' 和 'PersonNumber' 列。")

    # 步骤1: 使用crosstab生成基础频率矩阵
    # 任何非零计数在这里都被视为特征存在,对于二值化是合适的
    base_matrix = pd.crosstab(productusage_df["PersonNumber"], productusage_df["featureSk"])

    # 步骤2: 使用reindex来包含所有目标用户,并用0填充缺失值
    # 这会确保target_person_numbers中的所有用户都在结果中,
    # 并且对于未在base_matrix中出现的PersonNumber,其所有特征值都为0。
    final_matrix = base_matrix.reindex(target_person_numbers, fill_value=0)

    # 确保所有特征列都是整数类型 (0或1)
    # 虽然crosstab通常输出整数,但reindex可能导致类型变化,这里显式转换以保证结果一致性
    for col in final_matrix.columns:
        final_matrix[col] = final_matrix[col].astype(int)

    return final_matrix

# 示例数据
data = {
    'featureSk': ['A', 'B', 'C', 'C', 'A', 'B'],
    'PersonNumber': [1001, 1001, 1003, 1004, 1002, 1005]
}
productusage_df = pd.DataFrame(data)

# 测试目标用户列表
test_person_list = [1001, 1002, 1003, 9999] # 包含一个不存在的用户

# 调用函数生成特征矩阵
result_df = generate_binary_feature_matrix(productusage_df, test_person_list)

print("--- 最终生成的二值特征矩阵 ---")
print(result_df)

# 验证数据类型
print("\n--- 结果DataFrame信息 ---")
result_df.info()
登录后复制

输出:

--- 最终生成的二值特征矩阵 ---
featureSk     A  B  C
PersonNumber         
1001          1  1  0
1002          1  0  0
1003          0  0  1
9999          0  0  0

--- 结果DataFrame信息 ---
<class 'pandas.core.frame.DataFrame'>
Int64Index: 4 entries, 1001 to 9999
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype
---  ------  --------------  -----
 0   A       4 non-null      int64
 1   B       4 non-null      int64
 2   C       4 non-null      int64
dtypes: int64(3)
memory usage: 160.0 bytes
登录后复制

5. 注意事项与总结

  • 性能考量: pd.crosstab 和 reindex 是高度优化的Pandas操作,对于中等规模的数据集(数百万行),它们的性能远优于手动循环。
  • PySpark集成: 虽然本教程的解决方案是基于Pandas的,但如果您的原始数据是PySpark DataFrame,您可以先使用 .toPandas() 方法将其转换为Pandas DataFrame,然后再应用此逻辑。对于非常大的数据集,直接在PySpark中使用 groupBy 和 pivot 操作可能更高效,但这超出了本教程的范围。
  • 列的顺序: pd.crosstab 生成的列顺序是按特征名称的字母顺序排列的。如果需要特定的列顺序,可以在 reindex 之后使用 df[desired_column_order] 进行调整。
  • 数据类型: crosstab 默认输出整数类型。reindex 操作通常会保留类型,但为了确保结果的一致性,尤其是当 fill_value 可能导致类型推断为浮点数时,显式将列转换为 int 类型是一个好习惯。

通过利用Pandas的 pd.crosstab 和 reindex 函数,我们可以高效且优雅地将扁平化的事务数据转换为结构化的二值特征矩阵,这在数据预处理和特征工程中是非常实用的技巧。

以上就是生成二值特征矩阵:使用Pandas crosstab与reindex的高效方法的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号