在Pandas中按Provider分组,依据PotentialFraud多数值生成新DataFrame
解决Pandas中按Provider统计PotentialFraud多数值的KeyError问题
需求说明
现有包含Provider和PotentialFraud列的DataFrame,Provider存在重复编码,PotentialFraud为布尔类型。需生成新DataFrame,要求:
Provider列每个编码仅出现一次PotentialFraud值规则:原DataFrame中该Provider对应的True数量多于False则为True,否则为False
原DataFrame示例
| Provider | PotentialFraud |
|---|---|
| First | True |
| Second | True |
| First | True |
| Second | False |
| Third | False |
| Second | True |
目标DataFrame
| Provider | PotentialFraud |
|---|---|
| First | True |
| Second | True |
| Third | False |
问题代码及报错
尝试的循环代码:
final_provider_dataset = pd.DataFrame(columns=['Provider', 'PotentialFraud']) for provider in provider_test_dataset['Provider'].unique(): potential_fraud_true = provider_test_dataset[provider_test_dataset['Provider'] == provider] ['PotentialFraud'].value_counts()[True] potential_fraud_false = provider_test_dataset[provider_test_dataset['Provider'] == provider] ['PotentialFraud'].value_counts()[False] if potential_fraud_true > potential_fraud_false: final_provider_dataset = final_provider_dataset.append({'Provider': provider, 'PotentialFraud': True}, ignore_index=True) else: final_provider_dataset = final_provider_dataset.append({'Provider': provider, 'PotentialFraud': False}, ignore_index=True)
运行出现KeyError: True,原因是当某个Provider的PotentialFraud只有单一值时(比如示例中的Third全为False),value_counts()的结果中不存在对应的另一个布尔键,直接索引会触发KeyError。
解决方案
方案1:修改循环代码,用get方法避免KeyError
通过dict.get()方法获取计数,不存在时返回默认值0,避免索引报错:
final_provider_dataset = pd.DataFrame(columns=['Provider', 'PotentialFraud']) for provider in provider_test_dataset['Provider'].unique(): pf_counts = provider_test_dataset[provider_test_dataset['Provider'] == provider]['PotentialFraud'].value_counts() true_count = pf_counts.get(True, 0) false_count = pf_counts.get(False, 0) final_provider_dataset = final_provider_dataset.append( {'Provider': provider, 'PotentialFraud': true_count > false_count}, ignore_index=True )
方案2:用groupby+agg实现(推荐,更高效)
利用Pandas分组聚合功能,无需循环,性能更优:
# 分组后计算True的数量,再比较是否多于False final_df = provider_test_dataset.groupby('Provider')['PotentialFraud'].agg( lambda x: x.sum() > (len(x) - x.sum()) ).reset_index()
或者更直观的写法:
def majority_vote(x): true_count = x.value_counts().get(True, 0) false_count = x.value_counts().get(False, 0) return true_count > false_count final_df = provider_test_dataset.groupby('Provider')['PotentialFraud'].agg(majority_vote).reset_index()
方案3:用groupby+mean判断
因为布尔值True=1、False=0,均值大于0.5说明True数量更多:
final_df = provider_test_dataset.groupby('Provider')['PotentialFraud'].mean().reset_index() final_df['PotentialFraud'] = final_df['PotentialFraud'] > 0.5
以上三种方法都能得到符合需求的目标DataFrame,其中方案2和3避免了循环,更适合处理大数据量。
内容的提问来源于stack exchange,提问作者Kekko01
相关产品推荐
相关产品推荐

