Python数据分析与数据化运营

《Python数据分析与数据化运营》第二版 老代码与新代码对照信息

Author
宋天龙
发布于 2022-01-26
4370 次阅读
0 次赞
0 次分享
《Python数据分析与数据化运营》第二版 老代码与新代码对照信息
AI 智能核心导读

本文汇总了数据分析书籍2019版与最新版之间的代码差异及修复方案。重点梳理了因Python和R语言主流依赖库升级导致的语法变更,包括sklearn模块路径与评估指标调整、imblearn抽样函数更名、pyecharts图表重构、xlrd格式支持缩减,以及MySQL批量写库优化等,为解决方法弃用与报错问题提供标准参考。

第二版书籍代码更新与差异汇总(2019 版 vs 最新版)

由于第二版是 2019 年出版,某些库或方法可能已经过时,在此汇总新版本和之前书中的老版本的差异,供大家了解。

💡 排错指南:在遇到类似于“没有找到方法”、“无法找到”、“不存在”等类似问题时,可先在这里查看下是否存在现成的解决方案。

更新时间:2021-06-12


第一章

1.1 销售预测应用代码更新

第一章最后的“销售预测应用”部分中的代码需要更新,新版本中预测方法的输入参数格式发生了变化。

原始代码(老版本):

python
1new_x = 84610 2pre_y = model.predict(new_x) # 老版本 3 4print(pre_y)

新版本代码:

python
1new_x = 84610 2pre_y = model.predict([[new_x]]) # 新版本,需传入二维数组 3 4print(pre_y)

第二章

2.1 从 Excel 获取运营数据

在“2.2.2 从 Excel 获取运营数据”中,最新版本的 xlrd 已经不支持除了 .xls 以外的其他格式(功能有所缩减),因此使用方法发生变化。

原始代码(老版本支持 xlsx):

python
1# 打开文件 2xlsx = xlrd.open_workbook('demo.xlsx') # 老版本支持 xlsx 3 4# 查看所有 sheet 列表 5print('All sheets: %s' % xlsx.sheet_names())

新版本代码(仅支持 xls):

python
1# 打开文件 2xlsx = xlrd.open_workbook('demo.xls') # 新版本只支持 xls,其他格式均不支持 3 4# 查看所有 sheet 列表 5print('All sheets: %s' % xlsx.sheet_names())

第三章

3.1 数据清洗:缺失值处理库的变更

在“3.1 数据清洗:缺失值、异常值和重复值的处理”的“1. 缺失值处理”中,缺失值处理库的导入方法名称均已发生变化。

1. 导入库的变化

原始版本代码:

python
1import pandas as pd # 导入 pandas 库 2import numpy as np # 导入 numpy 库 3from sklearn.preprocessing import Imputer # 老版本,导入 sklearn.preprocessing 中的 Imputer 库

新版本代码:

python
1import pandas as pd # 导入 pandas 库 2import numpy as np # 导入 numpy 库 3from sklearn.impute import SimpleImputer # 新版本,导入 sklearn.impute 中的 SimpleImputer 库

2. 使用 sklearn 将缺失值替换为特定值

原始版本代码:

python
1# 使用 sklearn 将缺失值替换为特定值 2nan_model = Imputer(missing_values='NaN', strategy='mean', axis=0) # 老版本:将值为 NaN 的缺失值以均值做替换 3 4nan_result = nan_model.fit_transform(df) # 应用模型规则 5print(nan_result) # 打印输出

新版本代码:

python
1# 使用 sklearn 将缺失值替换为特定值 2# SimpleImputer 3nan_model = SimpleImputer(missing_values=np.nan, strategy='mean') # 新版本:将值为 NaN 的缺失值以均值做替换 4nan_result = nan_model.fit_transform(df) # 应用模型规则 5print(nan_result) # 打印输出

3.2 解决样本类别分布不均衡问题

在“3.4 解决样本类别分布不均衡的问题”中,imblearn 库的抽样方法名称发生了变化,统一将 fit_sample 更改为 fit_resample

1. 使用 SMOTE 方法进行过抽样处理

原始版本代码:

python
1# 使用 SMOTE 方法进行过抽样处理 2model_smote = SMOTE() # 建立 SMOTE 模型对象 3 4x_smote_resampled, y_smote_resampled = model_smote.fit_sample(x, y) # 老版本,输入数据并作过抽样处理 5 6x_smote_resampled = pd.DataFrame(x_smote_resampled, columns=['col1', 'col2', 'col3', 'col4', 'col5']) 7y_smote_resampled = pd.DataFrame(y_smote_resampled, columns=['label']) 8smote_resampled = pd.concat([x_smote_resampled, y_smote_resampled], axis=1) 9groupby_data_smote = smote_resampled.groupby('label').count() 10print(groupby_data_smote)

新版本代码:

python
1# 使用 SMOTE 方法进行过抽样处理 2model_smote = SMOTE() # 建立 SMOTE 模型对象 3 4x_smote_resampled, y_smote_resampled = model_smote.fit_resample(x, y) # 新版本,输入数据并作过抽样处理 5 6x_smote_resampled = pd.DataFrame(x_smote_resampled, columns=['col1', 'col2', 'col3', 'col4', 'col5']) 7y_smote_resampled = pd.DataFrame(y_smote_resampled, columns=['label']) 8smote_resampled = pd.concat([x_smote_resampled, y_smote_resampled], axis=1) 9groupby_data_smote = smote_resampled.groupby('label').count() 10print(groupby_data_smote)

2. 使用 RandomUnderSampler 方法进行欠抽样处理

原始版本代码:

python
1# 使用 RandomUnderSampler 方法进行欠抽样处理 2model_RandomUnderSampler = RandomUnderSampler() # 建立 RandomUnderSampler 模型对象 3 4x_RandomUnderSampler_resampled, y_RandomUnderSampler_resampled = model_RandomUnderSampler.fit_sample(x, y) # 老版本,输入数据并作欠抽样处理 5 6x_RandomUnderSampler_resampled = pd.DataFrame(x_RandomUnderSampler_resampled, columns=['col1', 'col2', 'col3', 'col4', 'col5']) 7y_RandomUnderSampler_resampled = pd.DataFrame(y_RandomUnderSampler_resampled, columns=['label']) 8RandomUnderSampler_resampled = pd.concat([x_RandomUnderSampler_resampled, y_RandomUnderSampler_resampled], axis=1) 9groupby_data_RandomUnderSampler = RandomUnderSampler_resampled.groupby('label').count() 10print(groupby_data_RandomUnderSampler)

新版本代码:

python
1# 使用 RandomUnderSampler 方法进行欠抽样处理 2model_RandomUnderSampler = RandomUnderSampler() # 建立 RandomUnderSampler 模型对象 3 4x_RandomUnderSampler_resampled, y_RandomUnderSampler_resampled = model_RandomUnderSampler.fit_resample(x, y) # 新版本,输入数据并作欠抽样处理 5 6x_RandomUnderSampler_resampled = pd.DataFrame(x_RandomUnderSampler_resampled, columns=['col1', 'col2', 'col3', 'col4', 'col5']) 7y_RandomUnderSampler_resampled = pd.DataFrame(y_RandomUnderSampler_resampled, columns=['label']) 8RandomUnderSampler_resampled = pd.concat([x_RandomUnderSampler_resampled, y_RandomUnderSampler_resampled], axis=1) 9groupby_data_RandomUnderSampler = RandomUnderSampler_resampled.groupby('label').count() 10print(groupby_data_RandomUnderSampler)

第四章

4.1 KMeans 的评估方法更新

在 KMeans 的评估方法中,新版本的 sklearn 已经去掉了 calinski_harabaz_score 方法

1. 导入库的变化

原始版本代码:

python
1from sklearn.metrics import silhouette_score, calinski_harabaz_score

新版本代码:

python
1from sklearn.metrics import silhouette_score # 效果评估模块,新版本中已经没有 calinski_harabaz_score 方法

2. 模型效果指标评估

原始版本代码:

python
1# 模型效果指标评估 2# 总样本量, 总特征数 3n_samples, n_features = raw_data.iloc[:,1:].shape 4print('samples: %d \t features: %d' % (n_samples, n_features)) 5 6# 非监督式评估方法 7silhouette_s = silhouette_score(scaled_numeric_features, model_kmeans.labels_, metric='euclidean') # 平均轮廓系数 8calinski_harabaz_s = calinski_harabaz_score(scaled_numeric_features, model_kmeans.labels_) # 老版本有,新版本没有该方法了 9unsupervised_data = {'silh':[silhouette_s], 'c&h':[calinski_harabaz_s]} # 老版本方法 10unsupervised_score = pd.DataFrame.from_dict(unsupervised_data) 11print('\n', 'unsupervised score:', '\n', '-'*60) 12print(unsupervised_score)

新版本代码:

python
1# 模型效果指标评估 2# 总样本量, 总特征数 3n_samples, n_features = raw_data.iloc[:,1:].shape 4print('samples: %d \t features: %d' % (n_samples, n_features)) 5 6# 非监督式评估方法 7silhouette_s = silhouette_score(scaled_numeric_features, model_kmeans.labels_, metric='euclidean') # 平均轮廓系数 8unsupervised_data = {'silh':[silhouette_s]} # 新版本方法,移除 c&h 指标 9unsupervised_score = pd.DataFrame.from_dict(unsupervised_data) 10print('\n', 'unsupervised score:', '\n', '-'*60) 11print(unsupervised_score)

4.2 回归分析:GradientBoostingRegressor 导入路径变化

在“4.2 回归分析-案例:大型促销活动前的销售预测”中,GradientBoostingRegressor 的导入来源库发生变化。

原始版本代码:

python
1from sklearn.ensemble.gradient_boosting import GradientBoostingRegressor # 老版本,集成算法

新版本代码:

python
1from sklearn.ensemble import GradientBoostingRegressor # 新版本方法

4.3 分类分析:SMOTE 调用方法变化

在“4.3 分类分析-案例:用户流失预测分析与应用”的“数据预处理”中,SMOTE 的调用方法由 fit_sample 变更为 fit_resample

原始版本代码:

python
1# 数据预处理 2# 填充缺失值 3X = X.fillna(X.mean()) 4# 样本均衡处理 5model_smote = SMOTE() # 建立 SMOTE 模型对象 6X, y = model_smote.fit_sample(X, y) # 老版本方法,输入数据并作过抽样处理

新版本代码:

python
1# 数据预处理 2# 填充缺失值 3X = X.fillna(X.mean()) 4# 样本均衡处理 5model_smote = SMOTE() # 建立 SMOTE 模型对象 6X, y = model_smote.fit_resample(X, y) # 新版本方法,输入数据并作过抽样处理

4.4 关联分析:pyecharts 库与 R 语言版本更新

在“4.4 关联分析”中,利用 Echarts 展示商品关联结果图时,由于 pyecharts 存在 v0.5 和 v1 两个互不兼容的版本,因此代码有较大差异。

1. 导入库的变化

原始版本代码:

python
1from pyecharts import Graph # 老版本导入库

新版本代码:

python
1from pyecharts.charts import Graph # 新版本导入 2from pyecharts import options as opts # 新版本导入配置方法库

2. 创建关系图的变化

原始版本代码:

python
1graph = Graph("商品关联结果图", width=800, height=800) 2graph.add("商品名称", nodes, edges, is_label_show=True, is_focusnode=True, is_roam=True, 3 repulsion=8000, graph_layout='circular', 4 line_width=2, label_text_size=14, is_random=True) 5graph

新版本代码:

python
1graph = Graph(init_opts=opts.InitOpts(width="800px", height="800px")) 2graph.add("", nodes, edges, repulsion=8000, layout="circular", is_rotate_label=True) 3graph.set_global_opts(title_opts=opts.TitleOpts(title="商品关联结果图")) 4graph.render_notebook()

3. R 语言版本升级说明

调用的 R 版本使用了最新的 R 4.1.0。其中涉及到的 R 部分代码略微做了修改,主要增加了判断库是否存在,如果不存在则自动安装的功能。具体代码如下:

r
1# 定义 R 脚本 2r_script = ''' 3 if (!require('arules')) 4 install.packages('arules') 5 library(arules) 6 data <- read.transactions("order_table.csv", format="single", header=TRUE, cols=c("order_id", "product_name"), sep=",") 7 init_rules <- apriori(data, parameter = list(support = 0.01, confidence = 0.05, minlen = 2)) 8 sort_rules <- sort(init_rules, by="lift") 9 rules_pd <- as(sort_rules, "data.frame") 10'''

4.5 时间序列分析:R 版本升级

“4.6 时间序列分析”中的 R 版本升级为最新的 R 4.1.0。经过测试,所有代码保持不变。


第五章

5.1 基于 RFM 的精细化用户管理:Bar3D 库更新

在“案例-基于 RFM 的精细化用户管理”中,Bar3D 库的导入和使用在原书 v0.5 和目前的 v1 版本中发生变化。

1. 导入库的变化

原始版本代码:

python
1from pyecharts import Bar3D # 老版本代码,3D 柱形图

新版本代码:

python
1from pyecharts.charts import Bar3D # 新版本代码,3D 柱形图 2from pyecharts import options as opts # 新版本代码,先导入配置方法库

2. RFM 图形展示的变化

原始版本代码:

python
1# 老版本,显示图形 2bar3d = Bar3D("", width=900, height=600) 3range_color = ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', 4 '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026'] 5bar3d.add( 6 "rfm 分组结果", 7 "", 8 "", 9 [d.tolist() for d in display_data.values], 10 is_visualmap=True, 11 visual_range=[0, display_data['number'].max()], 12 visual_range_color=range_color, 13 grid3d_width=200, 14 grid3d_height=80, 15 grid3d_depth=80 16) 17bar3d

新版本代码:

python
1# 新版本 2bar3d = Bar3D(init_opts=opts.InitOpts(width="900px", height="600px")) 3range_color = ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', 4 '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026'] 5data = [d.tolist() for d in display_data.values] 6bar3d.add( 7 series_name="rfm 分组结果", 8 data=data, 9 xaxis3d_opts=opts.Axis3DOpts(type_="category"), 10 yaxis3d_opts=opts.Axis3DOpts(type_="category"), 11 zaxis3d_opts=opts.Axis3DOpts(type_="value") 12) 13bar3d.set_global_opts( 14 visualmap_opts=opts.VisualMapOpts( 15 max_=display_data['number'].max(), 16 range_color=range_color, 17 ) 18 ) 19bar3d.render_notebook()

5.2 基于 RFM 的精细化用户管理:MySQL 写库方法改进

原书中的 MySQL 写库采用的是单条写库的方法,原始代码将 commit 放到 for 循环中,导致每次循环时都需要提交,效率极低:

python
1for each_value in write_db_data.values: 2 insert_sql = "INSERT INTO `%s` VALUES ('%s',%s,%s,%s,%s,'%s','%s')" % \ 3 (table_name, each_value[0], each_value[1], each_value[2], \ 4 each_value[3], each_value[4], each_value[5], 5 timestamp) # 写库 SQL 依据 6 cursor.execute(insert_sql) # 执行 SQL 语句,execute 函数里面要用双引号 7 con.commit() # 提交命令(在循环内,效率低)

为了提升速度,若仍使用单条写库操作,需要将 commit 放到 for 循环外面,即多次执行后一次性提交:

python
1for each_value in write_db_data.values: 2 insert_sql = "INSERT INTO `%s` VALUES ('%s',%s,%s,%s,%s,'%s','%s')" % \ 3 (table_name, each_value[0], each_value[1], each_value[2], \ 4 each_value[3], each_value[4], each_value[5], 5 timestamp) # 写库 SQL 依据 6 cursor.execute(insert_sql) # 执行 SQL 语句 7con.commit() # 提交命令(移至循环外)

最终优化方案:单条写库面对大量数据时仍然很慢,因此新版本改成了批量写库的方法,新代码具体为:

python
1batch_data = [[*each_value, timestamp] for each_value in write_db_data.values] 2query = f"INSERT INTO `{table_name}` VALUES (%s,%s,%s,%s,%s,%s,%s)" 3cursor.executemany(query, batch_data) # 执行 SQL 语句,executemany 函数批量写入 4con.commit() # 提交命令

5.3 营销响应预测:SMOTE 样本均衡使用方法变化

在“案例-基于嵌套 Pipeline 和 FeatureUnion 复合数据工作流的营销响应预测”中,样本均衡的 SMOTE 使用方法发生变化。

原始版本代码:

python
1x_smote_resampled, y_smote_resampled = model_smote.fit_sample(X_train, y_train) # 老版本,输入数据并作过抽样处理

新版本代码:

python
1x_smote_resampled, y_smote_resampled = model_smote.fit_resample(X_train, y_train) # 新版本,输入数据并作过抽样处理

第六章

6.1 投票组合模型的异常检测:SMOTE 应用方法变化

在“案例-基于集成算法 AdaBoost、GradientBoosting、RandomForest 和 Bagging 的投票组合模型的异常检测”中,样本均衡 SMOTE 应用方法发生变化。

原始版本代码:

python
1x_smote_resampled, y_smote_resampled = model_smote.fit_sample(X_train, y_train) # 老版本代码,输入数据并作过抽样处理

新版本代码:

python
1x_smote_resampled, y_smote_resampled = model_smote.fit_resample(X_train, y_train) # 新版本代码,输入数据并作过抽样处理

6.2 投票组合模型的异常检测:StratifiedKFold 参数变化

在同案例中,StratifiedKFold 模型交叉检验参数应用方法发生变化。

原始版本代码:

python
1# 交叉检验 2model_rf = RandomForestClassifier(max_features=0.8, random_state=0) # 随机森林分类模型对象 3model_gdbc = GradientBoostingClassifier(max_features=0.8, random_state=0) # GradientBoosting 分类模型对象 4 5estimators = [('randomforest', model_rf), ('gradientboosting', model_gdbc)] # 建立组合评估器列表 6model_vot = VotingClassifier(estimators=estimators, voting='soft', weights=[0.9, 1.2], n_jobs=-1) # 建立组合评估模型 7 8cv = StratifiedKFold(5, random_state=2) # 老版本代码,设置交叉检验方法 9 10cv_score = cross_val_score(model_gdbc, x_smote_resampled, y_smote_resampled, cv=cv) # 交叉检验 11print('{:*^60}'.format('Cross val scores:'), '\n', cv_score) # 打印每次交叉检验得分 12print('Mean scores is: %.2f' % cv_score.mean()) # 打印平均交叉检验得分

新版本代码:

python
1# 交叉检验 2model_rf = RandomForestClassifier(max_features=0.8, random_state=0) # 随机森林分类模型对象 3model_gdbc = GradientBoostingClassifier(max_features=0.8, random_state=0) # GradientBoosting 分类模型对象 4 5estimators = [('randomforest', model_rf), ('gradientboosting', model_gdbc)] # 建立组合评估器列表 6model_vot = VotingClassifier(estimators=estimators, voting='soft', weights=[0.9, 1.2], n_jobs=-1) # 建立组合评估模型 7 8cv = StratifiedKFold(5) # 新版本代码,移除了 random_state 参数 9 10cv_score = cross_val_score(model_gdbc, x_smote_resampled, y_smote_resampled, cv=cv) # 交叉检验 11print('{:*^60}'.format('Cross val scores:'), '\n', cv_score) # 打印每次交叉检验得分 12print('Mean scores is: %.2f' % cv_score.mean()) # 打印平均交叉检验得分

第七章

7.1 KMeans 广告效果聚类分析:雷达图 label 封装

在“案例-基于自动 K 值的 KMeans 广告效果聚类分析”最后输出雷达图时,新版本的 matplotlib.pyplot 需要额外对 label 做封闭处理

原始版本代码:

python
1# 交叉检验 2model_rf = RandomForestClassifier(max_features=0.8, random_state=0) # 随机森林分类模型对象 3model_gdbc = GradientBoostingClassifier(max_features=0.8, random_state=0) # GradientBoosting 分类模型对象 4 5estimators = [('randomforest', model_rf), ('gradientboosting', model_gdbc)] # 建立组合评估器列表 6model_vot = VotingClassifier(estimators=estimators, voting='soft', weights=[0.9, 1.2], n_jobs=-1) # 建立组合评估模型 7 8cv = StratifiedKFold(5) # 新版本代码,设置交叉检验方法 9 10cv_score = cross_val_score(model_gdbc, x_smote_resampled, y_smote_resampled, cv=cv) # 交叉检验 11print('{:*^60}'.format('Cross val scores:'), '\n', cv_score) # 打印每次交叉检验得分 12print('Mean scores is: %.2f' % cv_score.mean()) # 打印平均交叉检验得分

新版本代码:

python
1# part1 各类别数据预处理 2num_sets = cluster_pd.iloc[:6, :].T.astype(np.float64) # 获取要展示的数据 3num_sets_max_min = model_scaler.fit_transform(num_sets) # 获得标准化后的数据 4 5# part2 画布基本设置 6fig = plt.figure(figsize=(6, 6)) # 建立画布 7ax = fig.add_subplot(111, polar=True) # 增加子网格,注意 polar 参数 8labels = np.array(merge_data1.index) # 设置要展示的数据标签 9cor_list = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'] # 定义不同类别的颜色 10angles = np.linspace(0, 2 * np.pi, len(labels), endpoint=False) # 计算各个区间的角度 11angles = np.concatenate((angles, [angles[0]])) # 建立相同首尾字段以便于闭合 12 13labels = np.concatenate((labels, [labels[0]])) # 新版本增加,对 labels 进行封闭处理 14 15# part3 画雷达图 16for i in range(len(num_sets)): # 循环每个类别 17 data_tmp = num_sets_max_min[i, :] # 获得对应类数据 18 data = np.concatenate((data_tmp, [data_tmp[0]])) # 建立相同首尾字段以便于闭合 19 ax.plot(angles, data, 'o-', c=cor_list[i], label=i) # 画线 20 21# part4 设置图像显示格式 22ax.set_thetagrids(angles * 180 / np.pi, labels, fontproperties="SimHei") # 设置极坐标轴 23ax.set_title("各聚类类别显著特征对比", fontproperties="SimHei") # 设置标题放置 24ax.set_rlim(-0.2, 1.2) # 设置坐标轴尺度范围 25plt.legend(loc=0) # 设置图例位置

第八章

[暂无]

分享
最后修订: 2022-01-26