Pandas DataFrame交叉表按行计算元素占比概率的实现问题
问题解决
错误原因说明
- 你写的
prob = [i/sum(i) for i in range(df)]报错是因为range()只能接收整数参数,不能直接传入DataFrame对象,逻辑本身也不符合需求。 - 后续
apply写法结果不准是两个原因导致:第一apply默认axis=0按列计算,你需要的是按行维度计算需要指定axis=1;第二你用iloc[:, 1:]切掉了第一列数据,结果自然不符合预期。
方案1:直接用pd.crosstab自带参数实现(最简便)
pd.crosstab本身自带归一化参数,指定normalize='index'即可直接按行维度计算概率,无需后续二次处理:
import pandas as pd data = pd.DataFrame({'id_' : [1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010], 'A' : [1608, 1608, 2089, 213, 1005, 1887, 2089, 4544, 6866, 2020, 2020], 'B' : [1772, 1772, 1608, 1608, 1790, 1790, 1791, 1791, 1772, 1799, 1799], 'C': [1772,1608, 1005,1791, 4544, 2020, 1791, 1772, 1799, 2020, 213], }) # normalize='index'表示按行求和做归一化,round(2)保留两位小数得到0.33的效果 prob_df = pd.crosstab(data['B'], data['C'], normalize='index').round(2) print(prob_df)
方案2:对已有crosstab计数结果做行归一化
如果你已经生成了原始的计数df,调整apply的参数即可:
df = pd.crosstab(data['B'], data['C']) # axis=1指定逐行计算,每行元素除以该行的总和 prob_df = df.apply(lambda x: x/x.sum(), axis=1).round(2) print(prob_df)
方案3:不用crosstab的替代实现
用groupby+value_counts也可以实现需求:
# 按B分组,统计每组内C的取值占比,再unstack转成宽表格式 prob_df = data.groupby('B')['C'].value_counts(normalize=True).unstack(fill_value=0).round(2) print(prob_df)
三种方案运行后输出的结果都和你给出的预期结果完全一致。
内容的提问来源于stack exchange,提问作者Squid Game
相关产品推荐
相关产品推荐

