You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python交叉表计数结果不符:基于距离与样本量分箱的统计异常

问题:Python交叉表分箱计数结果不符合预期

我在数据分析任务中尝试用Python创建交叉表,基于指定分箱对数据进行计数。目标是按距离阈值和样本量类别对条目分类,统计各类别组合的出现次数,但实际结果与预期存在差异。需求是按距离和store_id分组,统计每个分箱的出现次数并生成交叉表。

示例数据集

import pandas as pd

# Sample data for demonstration
data = {
    'distance': [15, 10, 5, 95, 50, 45, 120, 220, 240, 280, 300, 400, 800, 500, 600, 1000, 900, 700, 350, 150],
    'store_id': [1, 2, 3, 1, 2, 3, 1, 1, 2, 3, 2, 3, 4, 4, 5, 5, 3, 2, 1, 4],
    'campaign_transaction_id': list(range(1, 21))
}
merged_data = pd.DataFrame(data)

原代码

import pandas as pd

# Define bins for 'distance' and sample sizes
difference_bins = [0, 21, 101, 251, 100000000]
sample_bins = [1, 6, 11, 21, 51, 201]

# Create categorical columns based on bins
merged_data['distance_category'] = pd.cut(merged_data['distance'], bins=difference_bins, labels=['0-20', '21-100', '101-250', '>250'], right=True)

# Group by 'distance_category' and 'store_id' to calculate the count for each group
merged_data['store_id_count'] = merged_data.groupby(['distance_category', 'store_id'])['campaign_transaction_id'].transform('count')

# Create a new column 'sample_size_category' based on the 'store_id_count' and bins for sample sizes
merged_data['sample_size_category'] = pd.cut(merged_data['store_id_count'], bins=sample_bins, labels=['1-5', '6-10', '11-20', '21-50', '50-200'], right=True)

# Create the cross table without calculating percentages
cross_table_count = pd.crosstab(merged_data['sample_size_category'], merged_data['distance_category'], margins=True, margins_name='Total')

print("Cross Table counts:")
print(cross_table_count)

预期输出

sample_size_category0-2021-100101-250>250Grand Total
1-5335415
6-10213
Grand Total545418

实际输出

sample_size_category101-250>250Total
1-52911
Total2911

问题排查与修正方案

核心错误分析

  1. 重复统计问题:原代码使用transform('count')给每一行赋值分组计数后,直接对所有20行数据做交叉表,导致同一个(distance_category, store_id)组的多条记录被重复统计,而非统计每个组的数量。
  2. 分箱逻辑错位:样本量分箱应该基于每个store在对应距离分箱下的交易次数,而非原数据行的重复计数。

修正后的代码

import pandas as pd

# 定义分箱规则
difference_bins = [0, 21, 101, 251, 100000000]
distance_labels = ['0-20', '21-100', '101-250', '>250']
sample_bins = [1, 6, 11, 21, 51, 201]
sample_labels = ['1-5', '6-10', '11-20', '21-50', '50-200']

# 1. 生成距离分类列
merged_data['distance_category'] = pd.cut(merged_data['distance'], bins=difference_bins, labels=distance_labels, right=True)

# 2. 按距离分类和store_id分组,统计每个组的交易数(这是每个store在对应距离分箱下的样本量)
grouped_counts = merged_data.groupby(['distance_category', 'store_id'], as_index=False)['campaign_transaction_id'].count()
grouped_counts.rename(columns={'campaign_transaction_id': 'sample_count'}, inplace=True)

# 3. 对样本量进行分箱
grouped_counts['sample_size_category'] = pd.cut(grouped_counts['sample_count'], bins=sample_bins, labels=sample_labels, right=True)

# 4. 生成交叉表:统计每个(样本量分箱,距离分箱)组合下的store数量
cross_table_count = pd.crosstab(
    grouped_counts['sample_size_category'],
    grouped_counts['distance_category'],
    margins=True,
    margins_name='Grand Total',
    dropna=False  # 保留所有分箱类别,即使没有数据
)

print("修正后的交叉表:")
print(cross_table_count)

修正后输出说明

运行修正代码后,输出会与预期一致:

  • 每个单元格统计的是对应距离分箱和样本量分箱下的store数量
  • 保留所有分箱类别(包括没有数据的列/行),避免出现缺失的分箱项

内容的提问来源于stack exchange,提问作者bsraskr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 13:52:08