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_category | 0-20 | 21-100 | 101-250 | >250 | Grand Total |
|---|---|---|---|---|---|
| 1-5 | 3 | 3 | 5 | 4 | 15 |
| 6-10 | 2 | 1 | 3 | ||
| Grand Total | 5 | 4 | 5 | 4 | 18 |
实际输出
| sample_size_category | 101-250 | >250 | Total |
|---|---|---|---|
| 1-5 | 2 | 9 | 11 |
| Total | 2 | 9 | 11 |
问题排查与修正方案
核心错误分析
- 重复统计问题:原代码使用
transform('count')给每一行赋值分组计数后,直接对所有20行数据做交叉表,导致同一个(distance_category, store_id)组的多条记录被重复统计,而非统计每个组的数量。 - 分箱逻辑错位:样本量分箱应该基于每个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
相关产品推荐
相关产品推荐

