import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import os
df = pd.read_excel('附件2:调查数据.xlsx') #, encoding='utf-8'
#print(df)
#df.info()
#df.isnull().any(axis=0) #查看空值
#counts = df.select_dtypes(include=['object']).apply(pd.Series.value_counts)
#print(counts)
#counts.to_excel("counts.xlsx")
#counts2 = df.apply(lambda x: x.value_counts())
#counts2
data=df.drop('序号',axis=1)
data.columns=['q1', 'q2', 'q3', 'q4', 'q5', 'q6', 'q7', 'q8', 'q9', 'q10',
'q11', 'q12', 'q13', 'q14', 'q15', 'q16', 'q17', 'q18', 'q19', 'q20',
'q21', 'q22', 'q23', 'q24', 'q25', 'q26', 'q27', 'q28', 'q29', 'q30']
#data
mapping = {'大一': 1, '大二': 2, '大三': 3, '大四': 4, '是': 1, '否': 0, '没考虑过': -1}
cols = ['q3', 'q7', 'q10', 'q11', 'q12', 'q13', 'q14', 'q15']
for col in cols:
data[col] = data[col].map(mapping)
data
data.to_excel("data.xlsx")
# 删除文件
if os.path.exists("data.xlsx"):
os.remove("data.xlsx")
print("文件已经删除!")
else:
print("要删除的文件不存在!")
data=pd.get_dummies(data,columns=['q1', 'q2', 'q4', 'q5', 'q6', 'q8', 'q9', 'q11',
'q16', 'q17', 'q18', 'q19', 'q20', 'q21', 'q22'])
data
# 定义多选题的列名列表
multi_select_cols = ['q23', 'q24', 'q25', 'q26', 'q27', 'q28', 'q29', 'q30']
# 遍历所有多选题,找到包含的所有选项
options = set()
for col in multi_select_cols:
for val in data[col].fillna('').unique():
if val:
val_list = val.split('┋')
options.update([o.strip() for o in val_list])
# 对于每个选项,新增一列并设置默认值为0
for option in options:
col_name = f'option_{option}'
data[col_name] = 0
# 遍历每个多选题样本,填充对应的值
for col in multi_select_cols:
for i, val in enumerate(data[col].fillna('')):
if val:
val_list = val.split('┋')
for v in val_list:
option_col = f'option_{v.strip()}'
data.loc[i, option_col] = 1
data
# 遍历每个多选题,重命名对应的选项列名
for col in multi_select_cols:
for val in data[col].fillna('').unique():
if val:
val_list = val.split('┋')
for v in val_list:
old_col_name = f'option_{v.strip()}'
new_col_name = f'{col}_{v.strip()}'
data = data.rename(columns={old_col_name: new_col_name})
data.to_excel("data.xlsx")
# 删除文件
if os.path.exists("data.xlsx"):
os.remove("data.xlsx")
print("文件已经删除!")
else:
print("要删除的文件不存在!")
data=data.drop(['q23', 'q24', 'q25', 'q26', 'q27', 'q28', 'q29', 'q30'],axis=1)
data
data.to_excel("data.xlsx")
# 删除文件
if os.path.exists("data.xlsx"):
os.remove("data.xlsx")
print("文件已经删除!")
else:
print("要删除的文件不存在!")
# 替换列名
df3 = data.rename(columns={'q3': 'q3_年级', 'q7': 'q7_是否使用', 'q10': 'q10_是否想获取', 'q12': 'q12_是否会选择',
'q13': 'q13_完成作业', 'q14': 'q14_完成小测验', 'q15': 'q15_完成论文'})
df3.to_excel("df3.xlsx")
df3.head()
相关性矩阵
df3.corr()
df3.describe()
# KS检验
def KsNormDetect(df3): # 输出结果是服从正态分布的数据列的名字
from scipy.stats import kstest
list_norm_T = [] # 用来储存服从正态分布的数据列的名字
for col in df3.columns:
u = df3[col].mean() # 计算均值
std = df3[col].std() # 计算标准差
res=kstest(df3[col], 'norm', (u, std))[1] # 计算P值
if res<=0.05: # 判断p值是否服从正态分布,p<=0.05 则服从正态分布,否则不服从
print(f'{col}该列数据服从正态分布------')
print('均值为:%.3f,标准差为:%.3f' % (u, std))
print('-'*40)
list_norm_T.append(col)
else: # 这一段实际上没什么必要
print(f'!!!{col}该列数据不服从正态分布**********')
print('均值为:%.3f,标准差为:%.3f' % (u, std))
print('*'*40)
#KsNormDetect(df3[['item_price', 'ord_qty']])
KsNormDetect(df3)
# 对待处理数据中心服从正态分布的数据列
def three_sigma(Ser1): # Ser1:表示传入DataFrame的某一列
rule = []
rule = (Ser1.mean()-3*Ser1.std()>Ser1) | (Ser1.mean()+3*Ser1.std()< Ser1)
out = Ser1.index[rule]
print(len(out))
return out # 返回落在3sigma之外的行索引值
def delete_out3sigma(df3, list_norm): # data:待检测的DataFrame;list_norm:服从正态分布的数据列名
out_index = [] # 保存要删除的行索引
for col in list_norm: # 对每一列分别用3sigma原则处理
index = three_sigma(df3[col])
out_index += index.tolist()
delete_ = list(set(out_index)) # 去除 out_index 中的重复元素
print(f'\n所删除的行索引共计{len(delete_)}个:\n',delete_)
df3.drop(delete_,inplace=True) # 根据 delete_ 删除对应行的数据
data3 = df3
return data3
#delete_out3sigma(df,['item_price','ord_qty'])
#delete_out3sigma(df3)
画图
sns.set(font='SimHei')
# Seaborn中设置字体-黑体,解决seaborn中文乱码问题
# 遍历每一列,并绘制对应的箱线图
for column in df3.columns:
fig, ax = plt.subplots()
ax.set_title(column)
ax.boxplot(df3[column])
plt.show()
# 遍历每一列,并绘制对应的条形图
for column in df3.columns:
fig, ax = plt.subplots()
ax.set_title(column)
ax.hist(df3[column], bins=len(set(df3[column])))
# 统计每列中不同元素的个数并输出
unique_elements = set(df3[column])
element_counts = [list(df3[column]).count(element) for element in unique_elements]
print('Column', column, 'Unique elements:', unique_elements, 'Counts:', element_counts)
plt.show()
建立模型
# 'q7_是否使用', 'q10_是否想获取', 'q12_是否会选择', 'q13_完成作业', 'q14_完成小测验', 'q15_完成论文'
df4=df3[['q7_是否使用', 'q10_是否想获取', 'q12_是否会选择', 'q13_完成作业', 'q14_完成小测验', 'q15_完成论文']].value_counts()
df4
# Text 2 ,提取自变量和因变量:
X = df3.drop(['q7_是否使用', 'q10_是否想获取', 'q12_是否会选择', 'q13_完成作业', 'q14_完成小测验', 'q15_完成论文'],axis=1)# 特征
y = df3[['q7_是否使用', 'q10_是否想获取', 'q12_是否会选择', 'q13_完成作业', 'q14_完成小测验', 'q15_完成论文']] # 目标变量
X
#分割数据:
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=100)
#用决策树进行尝试:
from sklearn.tree import DecisionTreeClassifier # 导入决策树
# 选择基尼系数作为判断标准,树深度为3
clf_gini = DecisionTreeClassifier(criterion='gini', max_depth=3, random_state=0)
clf_gini.fit(X_train, y_train) #训练模型
y_pred_gini = clf_gini.predict(X_test) # 预测模型
y_pred_gini[0:5] # 预测前五个结果
y_pred_gini
#可视化一下:
plt.figure(figsize=(12,8))
from sklearn import tree
tree.plot_tree(clf_gini.fit(X_train, y_train))
或者
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import MultiLabelBinarizer
from collections import defaultdict
import seaborn as sns
# 加载数据文件
data = pd.read_excel("附件2:调查数据.xlsx")
list(data)
# 前22列采用类别变量进行编码
# 第23列之后的列采用类别变量进行one-hot编码
df = data.iloc[:,23:]
# 对每一列进行多标签二值化编码
mlb = MultiLabelBinarizer()
cols = df.columns
for col in df.columns:
# 将每一列的数据按照分隔符进行分割
df[col] = df[col].apply(lambda x: x.split('┋') if isinstance(x, str) else x)
mlb.fit_transform(df[col])
# # 将编码结果按照列名展开为新的列
for i, label in enumerate(mlb.classes_):
data[f'{col}_{label}'] = df[col].apply(lambda x: 1 if label in x else 0)
data.drop(columns=df.columns,inplace=True)
data
list(data)
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['Simhei'] #显示中文
plt.rcParams['axes.unicode_minus'] = False #显示负号
# 筛选出单选题所在的列
single_choice_cols = data.columns[1:23]
# 绘制单选题的条形图和饼状图
for col in single_choice_cols:
# 计算每个选项的出现次数
value_counts = data[col].value_counts()
# 绘制条形图
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(value_counts.index, value_counts.values)
ax.set_title(col)
ax.set_xlabel('Answer Options')
ax.set_ylabel('Number of Responses')
plt.show()
# 绘制饼状图
fig, ax = plt.subplots(figsize=(10, 6))
ax.pie(value_counts.values, labels=value_counts.index, autopct='%1.1f%%', startangle=90)
ax.set_title(col)
plt.axis('equal')
plt.show()
# 绘制多选题的条形图和饼状图
for col in data.columns[23:]:
tmp = data[col].value_counts().sort_index()
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10,5))
ax1.bar(tmp.index.astype(str), tmp.values)
ax1.set_title(f"{col} - Frequency")
ax1.set_xlabel("Options")
ax1.set_ylabel("Count")
ax2.pie(tmp.values, labels=tmp.index, autopct='%1.1f%%')
ax2.set_title(f"{col} - Percentages")
plt.show()
# 单选题绘制条形图和饼状图
single_cols = data.columns[1:23]
for col in single_cols:
col_data = data[col].value_counts()
col_data.plot(kind='bar', rot=0, title=col)
plt.show()
col_data.plot(kind='pie', autopct='%1.1f%%', title=col)
plt.show()
# 多选题绘制条形图和饼状图
multi_cols = data.columns[23:]
multi_col_dict = {}
for col in multi_cols:
q_num = int(col.split('、')[0]) # 多选题问题编号
if q_num not in multi_col_dict:
multi_col_dict[q_num] = []
multi_col_dict[q_num].append(col)
for q_num, cols in multi_col_dict.items():
col_data = data[cols].sum().sort_values(ascending=False)
col_data.plot(kind='bar', rot=0, title=f'Multi-choice Question {q_num}')
plt.show()
col_data.plot(kind='pie', autopct='%1.1f%%', title=f'Multi-choice Question {q_num}')
plt.show()
data.to_excel("data2.xlsx")
df2=data.drop('序号',axis=1)
sns.set(font='SimHei')
# Seaborn中设置字体-黑体,解决seaborn中文乱码问题
# 遍历每一列,并绘制对应的条形图
for column in df2.columns[:22]:
fig, ax = plt.subplots()
ax.set_title(column)
ax.hist(df2[column], bins=len(set(df2[column])))
# 统计每列中不同元素的个数并输出
unique_elements = set(df2[column])
element_counts = [list(df2[column]).count(element) for element in unique_elements]
print('Column', column, 'Unique elements:', unique_elements, 'Counts:', element_counts)
plt.show()
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
plt.rcParams['font.sans-serif'] = ['Simhei'] #显示中文
#绘制箱线图
plt.figure(figsize=(10,6))
sns.boxplot(data=df2[:22])
plt.title('问题1至22中分布')
plt.show()
# 遍历每一列,并绘制对应的条形图和饼状图
for column in df2.columns[:22]:
# 绘制条形图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))
ax1.set_title(column)
ax1.hist(df2[column], bins=len(set(df2[column])))
# 统计每列中不同元素的个数并输出
unique_elements = set(df2[column])
element_counts = [list(df2[column]).count(element) for element in unique_elements]
print('Column', column, 'Unique elements:', unique_elements, 'Counts:', element_counts)
# 绘制饼状图
ax2.set_title(column + ' Proportions')
proportions = [count/len(df2[column]) for count in element_counts]
labels = list(unique_elements)
ax2.pie(proportions, labels=labels, autopct='%1.1f%%', startangle=90)
plt.show()