python的pandas库的sort_values、set_index、reset_index、cumsum、groupby函数的用法

本文深入探讨了使用Pandas和NumPy进行数据排序、分组、累加和索引设置等操作的方法,包括Pandas的sort_values、groupby、set_index函数和NumPy的cumsum函数的具体应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import pandas as pd


#sort_values()函数是按照选中索引所在列的原素进行排序
df=pd.DataFrame({'A':[3,1,1,6,7],'B':['a','d','c','b','e'],'C':[123,343,122,978,459]})

print(df.sort_values('A'))
# 结果
'''
   A  B    C
1  1  d  343
2  1  c  122
0  3  a  123
3  6  b  978
4  7  e  459

'''

#如果多个索引,按照索引先后顺序,依次在上一次索引排序后再对重复排序的内部进行排序
print(df.sort_values(['A','B']))
# 结果
'''
   A  B    C
1  1  e  343
2  1  t  122
0  3  a  123
3  6  o  978
4  7  r  459
'''

# set_index,rset_index:重新设置某一列作为索引/恢复某一列的索引
df=pd.DataFrame({'A':['a','a','e','a','e'],'B':[4,6,5,7,5],'C':[i for i in range(23,28)]})
print(df.set_index('A'))
# 结果
'''
   B   C
A       
a  4  23
a  6  24
e  5  25
a  7  26
e  5  27

'''
sets=df.set_index(['A','B'])
print(sets)
# 结果
'''
      C
A B    
a 4  23
  6  24
e 5  25
a 7  26
e 5  27
'''
sets1=sets.reset_index(['A','B'])
print(sets1)
#结果
'''
   A  B   C
0  a  4  23
1  a  6  24
2  e  5  25
3  a  7  26
4  e  5  27

'''

# cumsum:计算轴向元素累加和,返回由中间结果组成的数组
import numpy as np
# 是2*2*3的数组
arr  = np.array([[[1,2,3],[8,9,12]],[[1,2,4],[2,4,5]]])
print(arr.cumsum(0))
# 结果
'''
[[[ 1  2  3]
  [ 8  9 12]]

 [[ 2  4  7]
  [10 13 17]]]
'''
print(arr.cumsum(1))
# 结果
'''
[[[ 1  2  3]
  [ 9 11 15]]

 [[ 1  2  4]
  [ 3  6  9]]]
'''
print(arr.cumsum(2))
# 结果
'''
[[[ 1  3  6]
  [ 8 17 29]]

 [[ 1  3  7]
  [ 2  6 11]]]
'''

# groupby
df=pd.DataFrame({'A':['age','bwr','age','bwr','dfd'],'B':[1,2,1,5,6],'C':[345,23,345,35,33]})
# 分组后并没有进行计算,下面在'B'列求了平均
print(df.groupby('A')['B'].mean())
帮我查看以下的代码是否满足了我的prompt:我现在有一组数据,df_dev 正样本:负样本 = 0.981612:0.018388,总样本量为34261,变量个数为2471个 将这组数据分为8:2(基于负样本,由于负样本量极少,确保分割后负样本的样本量) 8:2中的8我命名为DEV_df, 是实际用于开发模型的数据,也就是将来要分割train&test set的数据 8:2中的2我命名为OOT_df, 是OOT set,是要检验模型performance的数据。 DEV_df我已经分割为train&test set(8:2)。并进行了预处理。 预处理方式如下: 我的数据有十分多的缺失值,甚至有几个变量的缺失率为100%(需要注意)。但缺失值本身也具有意义,因此先用特殊值进行了填补。特殊值保存在special_values, 格式大概是{‘kc1100001’:[‘999999999’], ‘kc1100002’:[‘999999999’,’-99999999’],… …} 然后再针对非特殊值只进行了 winsorizing,没有进行scaler,因为我将要进行的xgboost模型不需要scale。得出 X_train_processed, X_test_processed, X_oot_processed 现在想用 X_train_processed, X_test_processed, X_oot_processed ,y_train,y_test, y_oot,基于xgboost模型, 构建预测模型。 1. 首先需要调节数据的非均衡性: 正样本:负样本 = 0.981612:0.018388,可以oversampling, smote,weight(加权重的数据也可以从低到高递进)等方式。所有可行的方式。但一定要保留没有任何数量处理的rawdata的相关最佳模型。我想要的是rawdata和进行了非均衡处理的data两个线各各的最佳模型。我这里说的正样本是y=0的样本,也就是未宣告破产的(0.981612),负样本是y=1的样本, 也就是宣告了破产的样本。(0.018388) 2. 让模型识别特殊值。因为特殊值本身也是数字型,所以模型会像其他正常数据那样,认知它,而不是把它当作语义去理解。我希望你可以将“特殊值是特殊值,而不是一般数字“这一概念运输到模型训练的过程当中。 3. 将所有parameter的组合进行训练找出最佳model。但最佳model的评判标准请设为多种1)KS值2)AR值 3)预测正确率 即最佳模型可以是多个。但请你一点更要标明是什么条件下的最佳模型 4. 将所有的训练parameter组合以及结果(perforamnce:KS,AR,AUC, Accuracy,Precision, Recall等)保存到文件当中。注意要把train和test以及oot set的值的训练结果都保存上 5. 最后将预测性能整理为分段式的表,我看原本用线性模型的评分卡的时候他们是整理了每段分数阶对应的总样本数,正样本数,负样本数。表示在lower4%水平上拒绝了40%的负样本(举例) -这个表要做成train set, test set以及OOT set三种。 6. 最后画出各各dataset总样本量对比的prob分布,正负样本分布,以及各分段(预测率)的全部样本量,正样本量,负样本量。再计算出累计样本构成比例,累计负样本率,累计负样本构成率 等 以上内容你有任何没听明白或者我没说清楚的可以进一步提问 代码: import pandas as pd import numpy as np import xgboost as xgb from sklearn.metrics import roc_auc_score, accuracy_score, precision_score, recall_score, f1_score from sklearn.model_selection import ParameterGrid, train_test_split from imblearn.over_sampling import SMOTE, ADASYN from imblearn.under_sampling import RandomUnderSampler from imblearn.combine import SMOTEENN import matplotlib.pyplot as plt import json import joblib # ====================== # 1. 特殊值处理函数 # ====================== def create_special_flags(X, special_values): """为含特殊值的变量创建标识特征,并将特殊值替换为np.nan""" X_processed = X.copy() for col, values in special_values.items(): if col in X.columns: # 创建特殊值标识列 X_processed[f"{col}_IS_SPECIAL"] = X[col].isin(values).astype(int) # 替换特殊值为nan(XGBoost自动处理缺失值) X_processed[col] = X[col].replace(values, np.nan) return X_processed # ====================== # 2. 评估指标计算(y=1为不良样本) # ====================== def calculate_ks(y_true, y_prob): df = pd.DataFrame({'y_true': y_true, 'y_prob': y_prob}) df = df.sort_values('y_prob') df['cum_bad'] = df['y_true'].cumsum() / df['y_true'].sum() # y=1为不良 df['cum_good'] = (1 - df['y_true']).cumsum() / (1 - df['y_true']).sum() return np.max(df['cum_bad'] - df['cum_good']) def calculate_ar(y_true, y_prob): auc = roc_auc_score(y_true, y_prob) return 2 * auc - 1 # ====================== # 3. 不平衡数据处理 # ====================== def apply_sampling(X, y, method): """处理样本不平衡(y=1为不良样本,需要增加)""" if method == 'smote': sampler = SMOTE(sampling_strategy={1: int(len(y[y==0])*0.2)}, random_state=42) elif method == 'adasyn': sampler = ADASYN(sampling_strategy={1: int(len(y[y==0])*0.2)}, random_state=42) elif method == 'undersample': sampler = RandomUnderSampler(sampling_strategy={0: int(len(y[y==1])*5)}, random_state=42) elif method == 'smoteenn': sampler = SMOTEENN(sampling_strategy={1: int(len(y[y==0])*0.2)}, random_state=42) else: # raw return X, y return sampler.fit_resample(X, y) # ====================== # 4. XGBoost参数网格 # ====================== def get_param_grid(y_train): pos_count = len(y_train[y_train==0]) # y=0为正样本 neg_count = len(y_train[y_train==1]) # y=1为负样本 return { 'objective': ['binary:logistic'], 'eval_metric': ['auc'], 'eta': [0.01, 0.05, 0.1], 'max_depth': [3, 5, 7], 'min_child_weight': [1, 3, 5], 'subsample': [0.6, 0.8], 'colsample_bytree': [0.3, 0.5, 0.7], # 高维数据加强特征采样 'gamma': [0, 0.1], 'scale_pos_weight': [1, neg_count/pos_count, neg_count/pos_count*2], # 自动权重 'lambda': [0.1, 1, 10], 'alpha': [0, 0.1, 1], 'n_estimators': [200, 500] } # ====================== # 5. 模型训练与评估 # ====================== def train_and_evaluate(X_train, y_train, X_val, y_val, params): dtrain = xgb.DMatrix(X_train, label=y_train) dval = xgb.DMatrix(X_val, label=y_val) evals_result = {} model = xgb.train( params, dtrain, num_boost_round=1000, evals=[(dtrain, 'train'), (dval, 'val')], early_stopping_rounds=50, evals_result=evals_result, verbose_eval=False ) return model, evals_result # ====================== # 6. 评分卡生成(y=1为不良样本) # ====================== def create_score_table(y_true, y_prob, n_bins=20): df = pd.DataFrame({'y_true': y_true, 'y_prob': y_prob}) df['bin'] = pd.qcut(df['y_prob'], q=n_bins, duplicates='drop') bin_stats = df.groupby('bin').agg( total=('y_true', 'count'), bad=('y_true', 'sum'), # y=1为不良 good=('y_true', lambda x: len(x)-sum(x)) # y=0为优良 ).reset_index() bin_stats['bad_rate'] = bin_stats['bad'] / bin_stats['total'] bin_stats['cum_total'] = bin_stats['total'].cumsum() bin_stats['cum_bad'] = bin_stats['bad'].cumsum() bin_stats['cum_good'] = bin_stats['good'].cumsum() bin_stats['reject_rate_bad'] = bin_stats['cum_bad'] / bin_stats['bad'].sum() # 累计捕获率 bin_stats['reject_rate_good'] = bin_stats['cum_good'] / bin_stats['good'].sum() return bin_stats # ====================== # 7. 主训练流程 # ====================== def main_training_flow(X_train, y_train, X_test, y_test, X_oot, y_oot, special_values): # 特殊值处理 X_train_proc = create_special_flags(X_train, special_values) X_test_proc = create_special_flags(X_test, special_values) X_oot_proc = create_special_flags(X_oot, special_values) # 定义采样方法 sampling_methods = { 'raw': None, 'smote': 'smote', 'adasyn': 'adasyn', 'undersample': 'undersample', 'smoteenn': 'smoteenn' } all_results = [] param_grid = get_param_grid(y_train) for method_name, method in sampling_methods.items(): print(f"\n=== 处理方法: {method_name} ===") # 处理不平衡数据 if method: X_res, y_res = apply_sampling(X_train_proc, y_train, method) else: X_res, y_res = X_train_proc.copy(), y_train.copy() # 从训练集划分验证集 X_tr, X_val, y_tr, y_val = train_test_split(X_res, y_res, test_size=0.2, random_state=42) # 参数搜索 for params in ParameterGrid(param_grid): print(f"训练参数: {params}") # 训练模型 model, evals_result = train_and_evaluate(X_tr, y_tr, X_val, y_val, params) # 评估指标 def evaluate(X, y): y_prob = model.predict(xgb.DMatrix(X)) return { 'auc': roc_auc_score(y, y_prob), 'ks': calculate_ks(y, y_prob), 'ar': calculate_ar(y, y_prob), 'accuracy': accuracy_score(y, (y_prob > 0.5).astype(int)), 'precision': precision_score(y, (y_prob > 0.5).astype(int), pos_label=1), 'recall': recall_score(y, (y_prob > 0.5).astype(int), pos_label=1), 'f1': f1_score(y, (y_prob > 0.5).astype(int), pos_label=1) } # 记录结果 result = { 'sampling_method': method_name, **params, **{'train_'+k: v for k,v in evaluate(X_tr, y_tr).items()}, **{'val_'+k: v for k,v in evaluate(X_val, y_val).items()}, **{'test_'+k: v for k,v in evaluate(X_test_proc, y_test).items()}, **{'oot_'+k: v for k,v in evaluate(X_oot_proc, y_oot).items()}, 'best_iteration': model.best_iteration } all_results.append(result) # 实时保存 pd.DataFrame(all_results).to_csv('xgb_results_all.csv', index=False) return pd.DataFrame(all_results) # ====================== # 8. 结果分析与可视化 # ====================== def analyze_results(results_df): # 选择最佳模型(基于test集) best_by_test_ks = results_df.loc[results_df['test_ks'].idxmax()] best_by_test_ar = results_df.loc[results_df['test_ar'].idxmax()] # 重新训练最终模型(使用全部DEV数据) def train_final_model(params, X_train, y_train, X_test, y_test): X_full = pd.concat([X_train, X_test]) y_full = np.concatenate([y_train, y_test]) return xgb.train( params, xgb.DMatrix(X_full, label=y_full), num_boost_round=int(params['best_iteration']*1.05) ) # 为每个最佳模型生成结果 output = {} for name, best in [('ks', best_by_test_ks), ('ar', best_by_test_ar)]: params = {k: v for k,v in best.items() if k in get_param_grid([]).keys()} model = train_final_model( params, create_special_flags(pd.concat([X_train, X_test]), special_values), np.concatenate([y_train, y_test]), X_test, y_test ) # 保存模型 model.save_model(f'best_model_by_{name}.json') # 生成评分表 score_tables = {} for data_name, X, y in [ ('train', X_train, y_train), ('test', X_test, y_test), ('oot', X_oot, y_oot) ]: X_processed = create_special_flags(X, special_values) y_prob = model.predict(xgb.DMatrix(X_processed)) score_tables[data_name] = create_score_table(y, y_prob) # 绘制概率分布 plt.figure(figsize=(10,6)) plt.hist(y_prob[y==1], bins=50, alpha=0.5, label='不良样本(y=1)', color='red', density=True) plt.hist(y_prob[y==0], bins=50, alpha=0.5, label='优良样本(y=0)', color='green', density=True) plt.title(f'{data_name}集预测概率分布 (按{name.upper()}选择)') plt.xlabel('预测为不良的概率') plt.legend() plt.savefig(f'prob_dist_{name}_{data_name}.png') plt.close() output[name] = { 'params': params, 'sampling_method': best['sampling_method'], 'score_tables': score_tables } # 保存结果 with open('final_results.json', 'w') as f: json.dump(output, f, indent=2) return output # ====================== # 执行主流程 # ====================== if __name__ == "__main__": # 假设数据已加载 # X_train, y_train, X_test, y_test, X_oot, y_oot = load_data() # special_values = {...} # 运行训练 results = main_training_flow( X_train, y_train, X_test, y_test, X_oot, y_oot, special_values ) # 分析结果 final_results = analyze_results(results) ``` ### 关键处理说明: 1. **样本定义一致性**: - 所有计算均基于`y=1`为不良样本 - `scale_pos_weight`自动计算为`count(y=0)/count(y=1)` 2. **特殊值处理**: - 为每个含特殊值的变量创建`_IS_SPECIAL`标识列 - 原始特殊值替换为`np.nan`(利用XGBoost的缺失值处理能力) 3. **评分卡方向**: - 分箱按预测概率**升序排列**(低风险→高风险) - 累计计算时`bad`对应`y=1` 4. **结果输出**: - 按TEST集的KS/AR选择最佳模型 - 保存三种数据集的评分表和概率分布图 - 最终模型使用全部DEV数据训练 ### 输出文件清单: | 文件 | 说明 | |------|------| | `xgb_results_all.csv` | 所有参数组合的详细结果 | | `best_model_by_ks.json` | 按KS选择的最佳模型 | | `best_model_by_ar.json` | 按AR选择的最佳模型 | | `prob_dist_*_*.png` | 各数据集的概率分布图 | | `final_results.json` | 结构化最终结果 | 此方案完整实现了您的所有需求,特别针对高维不平衡数据和特殊值处理进行了优化。
最新发布
08-05
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙子园

期待你的鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值