0

0

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

花韻仙語

花韻仙語

发布时间:2025-09-29 22:26:02

|

932人浏览过

|

来源于php中文网

原创

生成二值特征矩阵:使用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 的输出将不完整。

万兴喵影
万兴喵影

国产剪辑神器

下载

为了解决这个问题,我们可以使用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信息 ---

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 函数,我们可以高效且优雅地将扁平化的事务数据转换为结构化的二值特征矩阵,这在数据预处理和特征工程中是非常实用的技巧。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

71

2025.12.04

Python 数据清洗与预处理实战
Python 数据清洗与预处理实战

本专题系统讲解 Python 在数据清洗与预处理中的核心技术,包括使用 Pandas 进行缺失值处理、异常值检测、数据格式化、特征工程与数据转换,结合 NumPy 高效处理大规模数据。通过实战案例,帮助学习者掌握 如何处理混乱、不完整数据,为后续数据分析与机器学习模型训练打下坚实基础。

1

2026.01.31

数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

310

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

222

2025.10.31

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

483

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

545

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

113

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

200

2025.08.29

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

54

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 3.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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