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


目录:

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

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

更新时间:2021-06-12


第一章

1.1 第一章最后的“销售预测应用”部分中的代码需要更新。

原始代码为:

new_x = 84610   
pre_y = model.predict(new_x) # 老版本

print(pre_y)

新版本中,需要改为:

new_x = 84610   
pre_y = model.predict([[new_x]]) # 新版本

print(pre_y)

第二章

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

原始代码为:

# 打开文件   
xlsx = xlrd.open_workbook('demo.xlsx') # 老版本支持xlsx

# 查看所有sheet列表   
print('All sheets: %s' % xlsx.sheet_names())

新版本为:

# 打开文件   
xlsx = xlrd.open_workbook('demo.xls') # 新版本只支持xls,其他格式均不支持

# 查看所有sheet列表   
print('All sheets: %s' % xlsx.sheet_names())

第三章

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

导入库

原始版本代码:

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

新版本的代码为:

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

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

原始版本代码:

# 使用sklearn将缺失值替换为特定值   
nan_model = Imputer(missing_values='NaN', strategy='mean', axis=0)  # 老版本,建立替换规则:将值为NaN的缺失值以均值做替换

nan_result = nan_model.fit_transform(df)  # 应用模型规则   
print(nan_result)  # 打印输出

新版本的代码为:

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

3.2 在“ 3.4 解决样本类别分布不均衡的问题 ”中,imblearn的库的用法发生变化。

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

原版本代码为:

# 使用SMOTE方法进行过抽样处理   
model_smote = SMOTE()  # 建立SMOTE模型对象

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

x_smote_resampled = pd.DataFrame(x_smote_resampled,   
                                 columns=['col1', 'col2', 'col3', 'col4', 'col5'])  # 将数据转换为数据框并命名列名   
y_smote_resampled = pd.DataFrame(y_smote_resampled, columns=['label'])  # 将数据转换为数据框并命名列名   
smote_resampled = pd.concat([x_smote_resampled, y_smote_resampled], axis=1)  # 按列合并数据框   
groupby_data_smote = smote_resampled.groupby('label').count()  # 对label做分类汇总   
print(groupby_data_smote)  # 打印输出经过SMOTE处理后的数据集样本分类分布

新版本代码:

# 使用SMOTE方法进行过抽样处理   
model_smote = SMOTE()  # 建立SMOTE模型对象

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

x_smote_resampled = pd.DataFrame(x_smote_resampled,   
                                 columns=['col1', 'col2', 'col3', 'col4', 'col5'])  # 将数据转换为数据框并命名列名   
y_smote_resampled = pd.DataFrame(y_smote_resampled, columns=['label'])  # 将数据转换为数据框并命名列名   
smote_resampled = pd.concat([x_smote_resampled, y_smote_resampled], axis=1)  # 按列合并数据框   
groupby_data_smote = smote_resampled.groupby('label').count()  # 对label做分类汇总   
print(groupby_data_smote)  # 打印输出经过SMOTE处理后的数据集样本分类分布

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

原始版本代码:

# 使用RandomUnderSampler方法进行欠抽样处理   
model_RandomUnderSampler = RandomUnderSampler()  # 建立RandomUnderSampler模型对象

x_RandomUnderSampler_resampled, y_RandomUnderSampler_resampled = model_RandomUnderSampler.fit_sample(

n x,
y) # 老版本,输入数据并作欠抽样处理

x_RandomUnderSampler_resampled = pd.DataFrame(x_RandomUnderSampler_resampled,   
                                              columns=['col1', 'col2', 'col3', 'col4',   
                                                       'col5'])  # 将数据转换为数据框并命名列名   
y_RandomUnderSampler_resampled = pd.DataFrame(y_RandomUnderSampler_resampled,   
                                              columns=['label'])  # 将数据转换为数据框并命名列名   
RandomUnderSampler_resampled = pd.concat(   
    [x_RandomUnderSampler_resampled, y_RandomUnderSampler_resampled],   
    axis=1)  # 按列合并数据框   
groupby_data_RandomUnderSampler = RandomUnderSampler_resampled.groupby(   
    'label').count()  # 对label做分类汇总   
print(groupby_data_RandomUnderSampler)  # 打印输出经过RandomUnderSampler处理后的数据集样本分类分布

新版本代码:

# 使用RandomUnderSampler方法进行欠抽样处理   
model_RandomUnderSampler = RandomUnderSampler()  # 建立RandomUnderSampler模型对象

x_RandomUnderSampler_resampled, y_RandomUnderSampler_resampled = model_RandomUnderSampler.fit_resample(   
    x,   
    y)  # 新版本,输入数据并作欠抽样处理

x_RandomUnderSampler_resampled = pd.DataFrame(x_RandomUnderSampler_resampled,   
                                              columns=['col1', 'col2', 'col3', 'col4',   
                                                       'col5'])  # 将数据转换为数据框并命名列名   
y_RandomUnderSampler_resampled = pd.DataFrame(y_RandomUnderSampler_resampled,   
                                              columns=['label'])  # 将数据转换为数据框并命名列名   
RandomUnderSampler_resampled = pd.concat(   
    [x_RandomUnderSampler_resampled, y_RandomUnderSampler_resampled],   
    axis=1)  # 按列合并数据框   
groupby_data_RandomUnderSampler = RandomUnderSampler_resampled.groupby(   
    'label').count()  # 对label做分类汇总   
print(groupby_data_RandomUnderSampler)  # 打印输出经过RandomUnderSampler处理后的数据集样本分类分布

第四章

4.1 Kmeans的评估方法,新版本中去掉了calinski_harabaz_score方法。

导入库

原始版本代码:

from sklearn.metrics import silhouette_score,calinski_harabaz_score

新版本代码:

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

模型效果指标评估

原始版本代码:

# 模型效果指标评估         
# 总样本量,总特征数         
n_samples, n_features = raw_data.iloc[:,1:].shape         
print('samples: %d \t features: %d' % (n_samples, n_features))

# 非监督式评估方法         
silhouette_s = silhouette_score(scaled_numeric_features, model_kmeans.labels_, metric='euclidean')  # 平均轮廓系数         
calinski_harabaz_s = calinski_harabaz_score(scaled_numeric_features, model_kmeans.labels_)  # 老版本有新版本没有该方法了         
unsupervised_data = {'silh':[silhouette_s],'c&h':[calinski_harabaz_s]} # 老版本方法         
unsupervised_score = pd.DataFrame.from_dict(unsupervised_data)         
print('\n','unsupervised score:','\n','-'*60)         
print(unsupervised_score)

新版本代码

# 模型效果指标评估         
# 总样本量,总特征数         
n_samples, n_features = raw_data.iloc[:,1:].shape         
print('samples: %d \t features: %d' % (n_samples, n_features))

# 非监督式评估方法         
silhouette_s = silhouette_score(scaled_numeric_features, model_kmeans.labels_, metric='euclidean')  # 平均轮廓系数         
unsupervised_data = {'silh':[silhouette_s]} # 新版本方法         
unsupervised_score = pd.DataFrame.from_dict(unsupervised_data)         
print('\n','unsupervised score:','\n','-'*60)         
print(unsupervised_score)

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

原始版本代码:

from sklearn.ensemble.gradient_boosting import GradientBoostingRegressor  # 老

版本,集成算法

新版本代码:

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

4.3 “ 4.3 分类分析-案例:用户流失预测分析与应用 ”中的“数据预处理”中的SMOTE的调用方法发生变化。

原始版本代码:

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

新版本代码

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

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

导入库

原始版本代码:

from pyecharts import Graph # 老版本导入库

新版本代码

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

创建关系图

原始版本代码

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

新版本代码

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

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

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

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


第五章

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

导入库

原始版本:

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

新版本代码

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

RFM图形展示

原始版本代码

# 老版本,显示图形   
bar3d = Bar3D("", width=900, height=600)   
range_color = ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf',   
               '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']   
bar3d.add(   
    "rfm分组结果",   
    "",   
    "",   
    [d.tolist() for d in display_data.values],   
    is_visualmap=True,   
    visual_range=[0, display_data['number'].max()],   
    visual_range_color=range_color,   
    grid3d_width=200,   
    grid3d_height=80,   
    grid3d_depth=80   
)   
bar3d

新版本代码:

# 新版本   
bar3d = Bar3D(init_opts=opts.InitOpts(width="900px", height="600px"))   
range_color = ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf',   
               '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']   
data = [d.tolist() for d in display_data.values]   
bar3d.add(   
    series_name="rfm分组结果",   
    data=data,   
    xaxis3d_opts=opts.Axis3DOpts(type_="category"),   
    yaxis3d_opts=opts.Axis3DOpts(type_="category"),   
    zaxis3d_opts=opts.Axis3DOpts(type_="value")   
)   
bar3d.set_global_opts(   
        visualmap_opts=opts.VisualMapOpts(

     max_ =display_data['number'].max(),   
            range_color=range_color,   
        )   
    )   
bar3d.render_notebook()

5.2 “ 案例-基于RFM的精细化用户管理 ”中 MySQL写库方法改进

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

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

这种方式会导致写库速度相当慢。因此,仍然是单条写库操作,需要将commit放到for外面,即多次执行后一次性提交:

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

但这种单条写库的操作,对于大量数据时仍然很慢,因此将改成批量写库的方法,新代码具体为:

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

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

原始代码版本:

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

新版本:

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

第六章

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

原始版本代码:

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

新版本代码:

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

6.2 “ 案例-基于集成算法AdaBoost、GradientBoosting、RandomForest和Bagging的投票组合模型的异常检测 ”中的StratifiedKFold模型交叉检验参数应用方法发生变化。

原始版本代码:

# 交叉检验   
model_rf = RandomForestClassifier(max_features=0.8, random_state=0)  # 随机森林分类模型对象   
model_gdbc = GradientBoostingClassifier(max_features=0.8, random_state=0)  # GradientBoosting分类模型对象

estimators = [('randomforest', model_rf), ('gradientboosting', model_gdbc)]  # 建立组合评估器列表   
model_vot = VotingClassifier(estimators=estimators, voting='soft', weights=[0.9, 1.2],   
                             n_jobs=-1)  # 建立组合评估模型

cv = StratifiedKFold(5, random_state=2)  # 老版本代码,设置交叉检验方法

cv_score = cross_val_score(model_gdbc, x_smote_resampled, y_smote_resampled, cv=cv)  # 交叉检验   
print('{:*^60}'.format('Cross val scores:'),'\n',cv_score) # 打印每次交叉检验得分   
print('Mean scores is: %.2f' % cv_score.mean())  # 打印平均交叉检验得分

新版本代码:

# 交叉检验   
model_rf = RandomForestClassifier(max_features=0.8, random_state=0)  # 随机森林分类模型对象   
model_gdbc = GradientBoostingClassifier(max_features=0.8, random_state=0)  # GradientBoosting分类模型对象

estimators = [('randomforest', model_rf), ('gradientboosting', model_gdbc)]  # 建立组合评估器列表   
model_vot = VotingClassifier(estimators=estimators, voting='soft', weights=[0.9, 1.2],   
                             n_jobs=-1)  # 建立组合评估模型

cv = StratifiedKFold(5)  # 新版本代码,设置交叉检验方法

cv_score = cross_val_score(model_gdbc, x_smote_resampled, y_smote_resampled, cv=cv)  # 交叉检验   
print('{:*^60}'.format('Cross val scores:'),'\n',cv_score) # 打印每次交叉检验

得分
print('Mean scores is: %.2f' % cv_score.mean()) # 打印平均交叉检验得分


第七章

7.1 “ 案例-基于自动K值的KMeans广告效果聚类分析 ”最后输出雷达图时,新版本的plt需要额外对label做封装。

原始代码为:

# 交叉检验   
model_rf = RandomForestClassifier(max_features=0.8, random_state=0)  # 随机森林分类模型对象   
model_gdbc = GradientBoostingClassifier(max_features=0.8, random_state=0)  # GradientBoosting分类模型对象

estimators = [('randomforest', model_rf), ('gradientboosting', model_gdbc)]  # 建立组合评估器列表   
model_vot = VotingClassifier(estimators=estimators, voting='soft', weights=[0.9, 1.2],   
                             n_jobs=-1)  # 建立组合评估模型

cv = StratifiedKFold(5)  # 新版本代码,设置交叉检验方法

cv_score = cross_val_score(model_gdbc, x_smote_resampled, y_smote_resampled, cv=cv)  # 交叉检验   
print('{:*^60}'.format('Cross val scores:'),'\n',cv_score) # 打印每次交叉检验得分   
print('Mean scores is: %.2f' % cv_score.mean())  # 打印平均交叉检验得分

新版本代码为:

# part1 各类别数据预处理   
num_sets = cluster_pd.iloc[:6, :].T.astype(np.float64)  # 获取要展示的数据   
num_sets_max_min = model_scaler.fit_transform(num_sets)  # 获得标准化后的数据   
# part2 画布基本设置   
fig = plt.figure(figsize=(6,6))  # 建立画布   
ax = fig.add_subplot(111, polar=True)  # 增加子网格注意polar参数   
labels = np.array(merge_data1.index)  # 设置要展示的数据标签   
cor_list = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'w']  # 定义不同类别的颜色   
angles = np.linspace(0, 2 * np.pi, len(labels), endpoint=False)  # 计算各个区间的角度   
angles = np.concatenate((angles, [angles[0]]))  # 建立相同首尾字段以便于闭合

labels = np.concatenate((labels,[labels[0]]))   # 新版本增加对labels进行封闭

# part3 画雷达图   
for i in range(len(num_sets)):  # 循环每个类别   
    data_tmp = num_sets_max_min[i, :]  # 获得对应类数据   
    data = np.concatenate((data_tmp, [data_tmp[0]]))  # 建立相同首尾字段以便于闭合   
    ax.plot(angles, data, 'o-', c=cor_list[i], label=i)  # 画线   
# part4 设置图像显示格式   
ax.set_thetagrids(angles * 180 / np.pi, labels, fontproperties="SimHei")  # 设置极坐标轴   
ax.set_title("各聚类类别显著特征对比", fontproperties="SimHei")  # 设置标题放置   
ax.set_rlim(-0.2, 1.2)  # 设置坐标轴尺度范围   
plt.legend(loc=0)  # 设置图例位置

第八章

[暂无]