目录
- 问题 1
- 1.1 对这些玻璃文物的表面风化与其玻璃类型、纹饰和颜色的关系进行分析
- 数据探索 -- 单个分类变量的绘图
- 树形图
- 条形图
- 扇形图
- 雷达图
- Cramer’s V 相关分析
- 统计检验
- 列联表分析
- 卡方检验
- Fisher检验
- 绘图
- 堆积条形图
- 分组条形图
- 分类模型
- Logistic回归
- 随机森林
import matplotlib.pyplot as plt
# Linux show Chinese characters *** important
plt.rcParams['font.family'] = 'WenQuanYi Micro Hei' import warnings
warnings.filterwarnings("ignore")
import pandas as pd# read by default 1st sheet of an excel file
path = '/home/shiyu/Desktop/path_acdemic/ant/数模/历年题目/2022/附件.xlsx'
d1 = pd.read_excel(path, sheet_name='表单1')
d2 = pd.read_excel(path, sheet_name='表单2')
d3 = pd.read_excel(path, sheet_name='表单3')print(d1.shape)
print(d2.shape)
print(d3.shape)
(58, 5)
(69, 15)
(8, 16)
问题 1
1.1 对这些玻璃文物的表面风化与其玻璃类型、纹饰和颜色的关系进行分析
数据探索 – 单个分类变量的绘图
树形图
https://www.geeksforgeeks.org/treemaps-in-python-using-squarify/
import seaborn as sb
import matplotlib.pyplot as plt
import squarifydata = list(d1['颜色'].value_counts())
labels = list(d1['颜色'].value_counts().index)plt.rcParams['figure.dpi'] = 300
plt.rcParams['savefig.dpi'] = 300plt.figure(figsize=(15,8))
squarify.plot(sizes=data, label=labels, text_kwargs={'fontsize': 20},color=sb.color_palette("Spectral",len(data))) plt.axis("off")
(0.0, 100.0, 0.0, 100.0)
条形图
df = pd.DataFrame(d1['颜色'].value_counts())
df['颜色'] = df.index
df
count | 颜色 | |
---|---|---|
颜色 | ||
浅蓝 | 20 | 浅蓝 |
蓝绿 | 15 | 蓝绿 |
深绿 | 7 | 深绿 |
紫 | 4 | 紫 |
浅绿 | 3 | 浅绿 |
深蓝 | 2 | 深蓝 |
黑 | 2 | 黑 |
绿 | 1 | 绿 |
import matplotlib.pyplot as plt
import plotly.express as px
import numpy as np# Linux show Chinese characters *** important
plt.rcParams['font.family'] = 'WenQuanYi Micro Hei' fig = px.bar(df, x="颜色", y="count", title="颜色类别计数")
# center title
fig.update_layout(title_x=0.5)
# remove background color
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
'paper_bgcolor': 'rgba(0, 0, 0, 0)',
})fig.show()
扇形图
print(d1['纹饰'].value_counts())
纹饰
C 30
A 22
B 6
Name: count, dtype: int64
import plotly.express as px
fig = px.pie(d1, names='纹饰', title="玻璃纹饰类别的比例分布")
# center title
fig.update_layout(title_x=0.5)
fig.show()
print(d1['类型'].value_counts())
fig = px.pie(d1, names='类型', title="玻璃类型的比例分布")
# center title
fig.update_layout(title_x=0.5)
fig.show()
类型
铅钡 40
高钾 18
Name: count, dtype: int64
print(d1['颜色'].value_counts())
fig = px.pie(d1, names='颜色', title="玻璃颜色的比例分布")
# center title
fig.update_layout(title_x=0.5)
fig.show()
颜色
浅蓝 20
蓝绿 15
深绿 7
紫 4
浅绿 3
深蓝 2
黑 2
绿 1
Name: count, dtype: int64
print(d1['表面风化'].value_counts())
fig = px.pie(d1, names='表面风化', title="表面风化和未风化的比例分布")
# center title
fig.update_layout(title_x=0.5)
fig.show()
表面风化
风化 34
无风化 24
Name: count, dtype: int64
雷达图
https://plotly.com/python/radar-chart/
df = pd.DataFrame(d1['颜色'].value_counts())
df['颜色'] = df.index
df
count | 颜色 | |
---|---|---|
颜色 | ||
浅蓝 | 20 | 浅蓝 |
蓝绿 | 15 | 蓝绿 |
深绿 | 7 | 深绿 |
紫 | 4 | 紫 |
浅绿 | 3 | 浅绿 |
深蓝 | 2 | 深蓝 |
黑 | 2 | 黑 |
绿 | 1 | 绿 |
import plotly.express as px
import pandas as pd
plt.rcParams['figure.dpi'] = 300
plt.rcParams['savefig.dpi'] = 300fig = px.line_polar(df, r='count', theta='颜色', line_close=False,title="颜色各类别计数")
fig.update_traces(fill='toself')
# center title
fig.update_layout(title_x=0.5)
fig.show()
表面风化 vs 纹饰
Cramer’s V 相关分析
Cramer’s V: 用于计算名义分类变量之间的相关性。
理论:
https://www.ibm.com/docs/en/cognos-analytics/11.1.0?topic=terms-cramrs-v
代码:
https://www.geeksforgeeks.org/how-to-calculate-cramers-v-in-python/
crosstab = pd.crosstab(d1['表面风化'],d1['纹饰'])# dataframe to numpy
d = crosstab.to_numpy()
d
array([[11, 0, 13],[11, 6, 17]])
import scipy.stats as stats
import numpy as np X2 = stats.chi2_contingency(d, correction=False)[0]
N = np.sum(d)
minimum_dimension = min(d.shape)-1# Calculate Cramer's V
result = np.sqrt((X2/N) / minimum_dimension) 'Cramer’s V 相关系数 表面风化 vs 纹饰 = ' + str(result)
'Cramer’s V 相关系数 表面风化 vs 纹饰 = 0.29233117579189066'
crosstab = pd.crosstab(d1['表面风化'],d1['类型'])
d = crosstab.to_numpy()X2 = stats.chi2_contingency(d, correction=False)[0]
N = np.sum(d)
minimum_dimension = min(d.shape)-1# Calculate Cramer's V
result = np.sqrt((X2/N) / minimum_dimension) 'Cramer’s V 相关系数 表面风化 vs 类型 = ' + str(result)
'Cramer’s V 相关系数 表面风化 vs 类型 = 0.3444233600968322'
crosstab = pd.crosstab(d1['表面风化'],d1['颜色'])
d = crosstab.to_numpy()X2 = stats.chi2_contingency(d, correction=False)[0]
N = np.sum(d)
minimum_dimension = min(d.shape)-1# Calculate Cramer's V
result = np.sqrt((X2/N) / minimum_dimension) 'Cramer’s V 相关系数 表面风化 vs 颜色 = ' + str(result)
'Cramer’s V 相关系数 表面风化 vs 颜色 = 0.34121631178560535'
统计检验
列联表分析
crosstab = pd.crosstab(d1['表面风化'],d1['纹饰'])
crosstab
纹饰 | A | B | C |
---|---|---|---|
表面风化 | |||
无风化 | 11 | 0 | 13 |
风化 | 11 | 6 | 17 |
卡方检验
https://www.geeksforgeeks.org/python-pearsons-chi-square-test/
import scipy.stats
from scipy.stats import chi2_contingency
# 表面风化 vs 纹饰
crosstab = pd.crosstab(d1['表面风化'],d1['纹饰'])
stat, p, dof, expected = chi2_contingency(crosstab)
# interpret p-value
alpha = 0.05
print("p value is " + str(p))
if p <= alpha:print('Dependent (reject H0)')
else:print('Independent (H0 holds true)')
p value is 0.08388839673210007
Independent (H0 holds true)
# 表面风化 vs 类型
crosstab = pd.crosstab(d1['表面风化'],d1['类型'])
stat, p, dof, expected = chi2_contingency(crosstab)
# interpret p-value
alpha = 0.05
print("p value is " + str(p))
if p <= alpha:print('Dependent (reject H0)')
else:print('Independent (H0 holds true)')
p value is 0.019548014331003307
Dependent (reject H0)
# 表面风化 vs 颜色
crosstab = pd.crosstab(d1['表面风化'],d1['颜色'])
stat, p, dof, expected = chi2_contingency(crosstab)
# interpret p-value
alpha = 0.05
print("p value is " + str(p))
if p <= alpha:print('Dependent (reject H0)')
else:print('Independent (H0 holds true)')
p value is 0.5066496855976865
Independent (H0 holds true)
Fisher检验
pd.crosstab(d1['表面风化'],d1['颜色'])
颜色 | 浅绿 | 浅蓝 | 深绿 | 深蓝 | 紫 | 绿 | 蓝绿 | 黑 |
---|---|---|---|---|---|---|---|---|
表面风化 | ||||||||
无风化 | 2 | 8 | 3 | 2 | 2 | 1 | 6 | 0 |
风化 | 1 | 12 | 4 | 0 | 2 | 0 | 9 | 2 |
import FisherExact as fsprint('表面风化 vs 颜色')
print(fs.fisher_exact(pd.crosstab(d1['表面风化'],d1['颜色'])))
表面风化 vs 颜色
0.0
绘图
堆积条形图
表面风化 vs 纹饰
crosstab = pd.crosstab(d1['表面风化'],d1['纹饰'])
crosstab
纹饰 | A | B | C |
---|---|---|---|
表面风化 | |||
无风化 | 11 | 0 | 13 |
风化 | 11 | 6 | 17 |
dp = [['无风化', '纹饰A', 11], ['无风化', '纹饰B', 0],['无风化', '纹饰C', 13],['风化', '纹饰A', 11],['风化', '纹饰B', 6],['风化', '纹饰C', 17]]# Create the pandas DataFrame
df = pd.DataFrame(dp, columns=['表面风化', '纹饰', '计数'])
df
表面风化 | 纹饰 | 计数 | |
---|---|---|---|
0 | 无风化 | 纹饰A | 11 |
1 | 无风化 | 纹饰B | 0 |
2 | 无风化 | 纹饰C | 13 |
3 | 风化 | 纹饰A | 11 |
4 | 风化 | 纹饰B | 6 |
5 | 风化 | 纹饰C | 17 |
import matplotlib.pyplot as plt
import plotly.express as px
import numpy as np# Linux show Chinese characters *** important
plt.rcParams['font.family'] = 'WenQuanYi Micro Hei' fig = px.bar(df, x="表面风化", y="计数", color="纹饰", title="表面风化与纹饰的关系")
# center title
fig.update_layout(title_x=0.5)
# remove background color
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
'paper_bgcolor': 'rgba(0, 0, 0, 0)',
})fig.show()
表面风化 vs 玻璃类型
crosstab = pd.crosstab(d1['表面风化'],d1['类型'])
crosstab
类型 | 铅钡 | 高钾 |
---|---|---|
表面风化 | ||
无风化 | 12 | 12 |
风化 | 28 | 6 |
dp = [['无风化', '铅钡', 12], ['无风化', '高钾', 12],['风化', '铅钡', 28],['风化', '高钾', 6]]# Create the pandas DataFrame
df = pd.DataFrame(dp, columns=['表面风化', '玻璃类型', '计数'])
df
表面风化 | 玻璃类型 | 计数 | |
---|---|---|---|
0 | 无风化 | 铅钡 | 12 |
1 | 无风化 | 高钾 | 12 |
2 | 风化 | 铅钡 | 28 |
3 | 风化 | 高钾 | 6 |
fig = px.bar(df, x="表面风化", y="计数", color="玻璃类型", title="表面风化与玻璃类型的关系")
# center title
fig.update_layout(title_x=0.5)
# remove background color
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
'paper_bgcolor': 'rgba(0, 0, 0, 0)',
})fig.show()
表面风化 vs 颜色
crosstab = pd.crosstab(d1['表面风化'],d1['颜色'])
crosstab
颜色 | 浅绿 | 浅蓝 | 深绿 | 深蓝 | 紫 | 绿 | 蓝绿 | 黑 |
---|---|---|---|---|---|---|---|---|
表面风化 | ||||||||
无风化 | 2 | 8 | 3 | 2 | 2 | 1 | 6 | 0 |
风化 | 1 | 12 | 4 | 0 | 2 | 0 | 9 | 2 |
col1 = pd.DataFrame(['无风化'] * crosstab.shape[1] + ['风化'] * crosstab.shape[1])
col2 = pd.DataFrame(list(crosstab.columns) * 2)
col3 = pd.DataFrame(list(crosstab.iloc[0]) + list(crosstab.iloc[1]))df = pd.concat([col1, col2, col3], axis=1)
df.columns = ['表面风化', '颜色', '计数']
df
表面风化 | 颜色 | 计数 | |
---|---|---|---|
0 | 无风化 | 浅绿 | 2 |
1 | 无风化 | 浅蓝 | 8 |
2 | 无风化 | 深绿 | 3 |
3 | 无风化 | 深蓝 | 2 |
4 | 无风化 | 紫 | 2 |
5 | 无风化 | 绿 | 1 |
6 | 无风化 | 蓝绿 | 6 |
7 | 无风化 | 黑 | 0 |
8 | 风化 | 浅绿 | 1 |
9 | 风化 | 浅蓝 | 12 |
10 | 风化 | 深绿 | 4 |
11 | 风化 | 深蓝 | 0 |
12 | 风化 | 紫 | 2 |
13 | 风化 | 绿 | 0 |
14 | 风化 | 蓝绿 | 9 |
15 | 风化 | 黑 | 2 |
fig = px.bar(df, x="表面风化", y="计数", color="颜色", title="表面风化与颜色的关系")
# center title
fig.update_layout(title_x=0.5)
# remove background color
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
'paper_bgcolor': 'rgba(0, 0, 0, 0)',
})fig.show()
分组条形图
fig = px.bar(df, x="表面风化", y="计数", color="颜色", title="表面风化与颜色的关系", barmode='group')
# center title
fig.update_layout(title_x=0.5)
# remove background color
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
'paper_bgcolor': 'rgba(0, 0, 0, 0)',
})fig.show()
分类模型
Logistic回归
https://www.w3schools.com/python/python_ml_logistic_regression.asp
import sklearn
import warnings
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn import linear_modeld1['颜色'].fillna('浅蓝', inplace=True)
df = d1.iloc[:,1:5]
# data encode
label_encoder = LabelEncoder()
df_encode = df.select_dtypes(include=['object']).apply(label_encoder.fit_transform)
df_encode.head()
纹饰 | 类型 | 颜色 | 表面风化 | |
---|---|---|---|---|
0 | 2 | 1 | 6 | 0 |
1 | 0 | 0 | 1 | 1 |
2 | 0 | 1 | 6 | 0 |
3 | 0 | 1 | 6 | 0 |
4 | 0 | 1 | 6 | 0 |
X = df_encode.drop('表面风化', axis=1)
y = df_encode['表面风化']logr = linear_model.LogisticRegression()
logr.fit(X,y)print('截距项 = ' + str(logr.intercept_))log_odds = logr.coef_
odds = numpy.exp(log_odds)
print('回归系数= ' + str(odds))
截距项 = [0.20030893]
回归系数= [[1.12409879 0.24081195 1.1795666 ]]
随机森林
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
import pandas as pd
#import shap
from sklearn.metrics import accuracy_score
import numpy as np
clf = RandomForestClassifier(n_estimators=100, random_state=42)
clf.fit(X, y)importances = clf.feature_importances_
feature_imp_df = pd.DataFrame({'变量名': X.columns, '重要性程度': importances}).sort_values('重要性程度', ascending=True)
feature_imp_df
变量名 | 重要性程度 | |
---|---|---|
0 | 纹饰 | 0.270358 |
1 | 类型 | 0.297645 |
2 | 颜色 | 0.431998 |
import matplotlib.pyplot as plt
import plotly.express as px
import numpy as np# Linux show Chinese characters *** important
plt.rcParams['font.family'] = 'WenQuanYi Micro Hei' fig = px.bar(feature_imp_df, y="变量名", x="重要性程度",title="表面风化与其玻璃类型、纹饰和颜色的关系强度", orientation='h')
# center title
fig.update_layout(title_x=0.5)
# remove background color
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
'paper_bgcolor': 'rgba(0, 0, 0, 0)',
})fig.show()
相关阅读:
- 2022高教社杯全国大学生数学建模竞赛C题 问题一(2) Python代码
- 2022高教社杯全国大学生数学建模竞赛C题 问题一(3) Python代码
- 2023高教社杯全国大学生数学建模竞赛C题 Python代码