步骤:数据获取,探索分析与可视化,预处理理论,分析建模,模型评估
数据获取手段:
(1) 数据仓库(DW)
(2) 监测与抓取
(3) 填写、日志、埋点
(4) 计算
数据学习网站
(1)数据竞赛网站(Kaggle&天池)
(2)数据集网站(ImageNet/Open Images)
(3)各领域统计数据(统计局、政府机构、公司财报等)
import pandas as pd
df = pd.read_csv("./data/HR.csv")
print(df.head(10))
探索性数据分析(单因子与对比分析)可视化
(1)理论:
(2)代码实现
import pandas as pd
import scipy.stats as ss
df = pd.read_csv("./data/HR.csv") # 可以加sep参数作为分隔符
print(df.mean()) # 均值
print(df["satisfaction_level"].mean())
print(df.median()) # 中位数
print(df["satisfaction_level"].median())
print(df.quantile(q=0.25)) # 分位数,q=0.25 表示四分位数
print(df["satisfaction_level"].quantile(q=0.25))
print(df.mode()) # 众数
print(df["satisfaction_level"].mode())
print(df.std()) # 标准差,离中趋势
print(df["satisfaction_level"].std())
print(df.var()) # 方差
print(df["satisfaction_level"].var())
print(df.sum()) # 求和,离散数据求和是直接连起来
print(df["satisfaction_level"].sum())
print(df.skew()) # 偏态系数
print(df["satisfaction_level"].skew())
print(df.kurt()) # 峰度系数,以正态分布为0作为标准
print(df["satisfaction_level"].kurt())
print(ss.norm.stats(moments="mvsk")) # 正态分布的性质,m:均值 v:方差 s:偏态系数 k:峰态系数
print(ss.norm.pdf(0.0)) # 正态分布指定横坐标返回纵坐标的值
print(ss.norm.ppf(0.9)) # 输入的值必须是0到1之间的,从负无穷累积的值
print(ss.norm.cdf(2)) # 从负无穷累积到2,累积概率是多少
print(ss.norm.cdf(2) - ss.norm.cdf(-2)) # 正态分布中-2到2的累积概率
print(ss.norm.rvs(size=10)) # 得到10个符合正态分布的数字
print(ss.chi2) # 卡方分布
print(ss.t) # t分布
print(ss.f) # f 分布
print(df.sample(n=10)) # 抽样,抽n个
print(df["satisfaction_level"].sample(10))
print(df.sample(frac=0.001)) # 抽样,frac参数指定百分比
数据分类
(1)定类(类别):根据事物离散、无差别属性进行分类(男,女)
(2)定序(顺序):可以界定数据的大小,但不能测定差值。数据间有差距但不能测定差距的大小(收入低,中,高)
(3)定距(间隔):可以界定数据大小的同时,可测定差值,但无绝对零点。乘法除法和比率没有意义(摄氏度)
(4)定比(比率):可以界定数据的大小,可测定差值,有绝对零点(身高,体重)
单属性分析
(1)异常值分析:离散异常值,连续异常值,常识异常值
(2)对比分析:绝对数与相对数,时间,空间,理论维度比较
(3)结构分析:各组成部分的分布与规律
(4)分布分析:数据分布频率的显式分析
import pandas as pd
import numpy as np
df = pd.read_csv("./data/HR.csv")
#### satisfaction_level的分析 ####
sl_s = df["satisfaction_level"]
print(sl_s.isnull()) # 判断是否为空
print(sl_s[sl_s.isnull()]) # 寻找异常值
print(df[df["satisfaction_level"].isnull()]) # 显示存在异常的数据
sl_s = sl_s.dropna() # 丢弃异常值
# sl_s = sl_s.fillna() # 填充异常值
print(sl_s.mean()) # 均值
print(sl_s.std()) # 标准差
print(sl_s.max()) # 最大值
print(sl_s.min()) # 最小值
print(sl_s.median()) # 中位数
print(sl_s.quantile(q=0.25)) # 下四分位数
print(sl_s.quantile(q=0.75)) # 上四分位数
print(sl_s.skew()) # 偏态系数
print(sl_s.kurt()) # 峰态系数
print(np.histogram(sl_s.values, bins=np.arange(0.0, 1.1, 0.1))) # 第一个参数:要切分的值,第二个参数:切分的临界值,np.arrange(开始值,结束值,间隔)
#### last_evaluation的分析 ####
le_s = df["last_evaluation"]
print(le_s[le_s.isnull()]) # 找出空值
print(le_s.mean()) # 均值
print(le_s.std()) # 标准差
print(le_s.median()) # 中位数
print(le_s.max()) # 最大值
print(le_s.min()) # 最小值
print(le_s.skew()) # 偏态系数
print(le_s.kurt()) # 峰态系数
# 异常值:四分位间距: 上四分位数 - 下四分位数 上界:上四位数 + 1.5~3 * 四分位间距 下界:下四位数 - 1.5~3 * 四分位间距 上下界之间为正常值,上下界以外的为异常值
print(le_s[le_s > 1]) # 均值出现异常,且偏态系数和峰态系数过大,寻找异常值
le_s = le_s[le_s <= 1] # 去掉异常值
q_low = le_s.quantile(q=0.25) # 下四分位数
q_high = le_s.quantile(q=0.75) # 上四分位数
q_interval = q_high - q_low # 四分位间距
k = 1.5
le_s = le_s[le_s < q_high + k * q_interval][le_s > q_low - k * q_interval] # 去掉异常值
print(np.histogram(le_s.values, bins=np.arange(0, 1.1, 0.1))) # 统计不同取值区间内的数有多少个
print(le_s.mean()) # 平均值
print(le_s.std()) # 标准差
print(le_s.median()) # 中位数
print(le_s.max()) # 最大值
print(le_s.skew()) # 偏度系数
print(le_s.kurt()) # 峰度系数
#### number_project的分析 ####
np_s = df["number_project"]
print(np_s[np_s.isnull()]) # 寻找空值
print(np_s.mean()) # 均值
print(np_s.std()) # 标准差
print(np_s.median()) # 中位数
print(np_s.max()) # 最大值
print(np_s.min()) # 最小值
print(np_s.skew()) # 偏态系数
print(np_s.kurt()) # 峰态系数
print(np_s.value_counts()) # 计算不同的值出现了多少次
print(np_s.value_counts(normalize=True)) # 计算不同的值出现的比例
print(np_s.value_counts(normalize=True).sort_index()) # 根据数据的index进行排序
#### average_montly_hours的分析 ####
amh_s = df["average_monthly_hours"]
print(amh_s.mean()) # 平均值
print(amh_s.std()) # 标准差
print(amh_s.max()) # 最大值
print(amh_s.min()) # 最小值
print(amh_s.skew()) # 偏态系数
print(amh_s.kurt()) # 峰态系数
q_low = amh_s.quantile(q=0.25) # 下四分位数
q_high = amh_s.quantile(q=0.75) # 上四分位数
q_interval = q_high - q_low # 四分位间距
k = 1.5
amh_s = amh_s[amh_s < q_high + k * q_interval][amh_s > q_low - k * q_interval] # 去除异常值
print(len(amh_s))
print(np.histogram(amh_s.values, bins=10)) # bins=数字 表示直接分成几分
print(np.histogram(amh_s.values, bins=np.arange(amh_s.min(), amh_s.max() + 10, 10))) # 左闭右开区间
print(amh_s.value_counts(bins=np.arange(amh_s.min(), amh_s.max() + 10, 10))) # 左开右闭区间
#### time_spend_company的分析 ####
tsc_s = df["time_spend_company"]
print(tsc_s.value_counts().sort_index()) # 按照数据的index排序
print(tsc_s.mean()) # 平均值
#### Work_accident的分析 ####
wa_s = df["Work_accident"]
print(wa_s.value_counts())
print(wa_s.mean()) # 事故率和均值相同
#### left的分析 ####
l_s = df["left"]
print(l_s.value_counts())
#### promotion_last_5years的分析 ####
pl5_s = df["promotion_last_5years"]
print(pl5_s.value_counts()) # 查看数据的分布
#### salary的分析 ####
s_s = df["salary"]
print(s_s.value_counts())
print(s_s.where(s_s!="nme")) # 寻找异常值,s_s.where(s_s!="nme")将 nme 取成空
s_s.where(s_s!="nme").dropna() # 去掉异常值
#### department的分析 ####
d_s = df["department"]
print(d_s.value_counts(normalize=True)) # 计算不同数据出现的概率
d_s = d_s.where(d_s != "sale") # 此时sale处的数据变成了空
d_s.dropna() # 去掉异常值
import pandas as pd
import numpy as np
df = pd.read_csv("./data/HR.csv")
sl_s = df["satisfaction_level"]
le_s = df["last_evaluation"]
np_s = df["number_project"]
amh_s = df["average_monthly_hours"]
tsc_s = df["time_spend_company"]
wa_s = df["Work_accident"]
l_s = df["left"]
pl5_s = df["promotion_last_5years"]
s_s = df["salary"]
d_s = df["department"]
#### 去除异常值
df = df.dropna(axis=0, how="any") # 去除空值,axis指定坐标轴,0为横坐标,1为纵坐标,how="all"这一行全是空值时才去掉 how="any"这一行有一个空值就去掉
df = df[le_s <= 1][s_s != "nme"][d_s != "sale"] # 去除异常值
#### 对比分析
print(df.groupby("department").mean()) # 根据部门进行分组,并取均值
print(df.loc[:, ["last_evaluation", "department"]].groupby("department").mean()) # 切片后分组并取均值
print(df.loc[:, ["average_monthly_hours", "department"]].groupby("department")["average_monthly_hours"].apply(lambda x:x.max() - x.min())) # 切片后分组,并计算极差
可视化
(1)柱状图
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_style(style="darkgrid")
sns.set_context(context="paper")
sns.set_palette("Reds")
df = pd.read_csv("./data/HR.csv")
#### seaborn绘制 ####
sns.countplot(x="salary", hue="department", data=df) # hue:进行多层绘制,以department为分割,又进行了一次绘制
plt.show()
#### matplotlib绘制 ####
plt.title("SALARY") # 标题
plt.xlabel("salary") # 横轴名称
plt.ylabel("number") # 纵轴名称
plt.xticks(np.arange(len(df["salary"].value_counts()))+0.5, df["salary"].value_counts().index) # 在横轴做标记
plt.axis([0, 4, 0, 10000]) # axis([横轴最小值, 横轴最大值, 纵轴最小值, 纵轴最大值]) # 显示设置
plt.bar(np.arange(len(df["salary"].value_counts()))+0.5, df["salary"].value_counts(), width=0.5) # +0.5是为了在正中间显示, width设置柱子的宽度
for x, y in zip(np.arange(len(df["salary"].value_counts()))+0.5, df["salary"].value_counts()):
plt.text(x, y, y, ha="center", va="bottom") # plt.text(横坐标, 纵坐标, 添加文本, 水平位置, 垂直位置)
plt.show()
(2)直方图
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_style(style="darkgrid")
sns.set_context(context="paper")
sns.set_palette("Reds")
df = pd.read_csv("./data/HR.csv")
f = plt.figure()
f.add_subplot(1, 3, 1)
sns.distplot(df["satisfaction_level"], bins=10) # bins=n, 分成n份
f.add_subplot(1, 3, 2)
sns.distplot(df["last_evaluation"], bins=10)
f.add_subplot(1, 3, 3)
sns.distplot(df["average_monthly_hours"], bins=10)
plt.show()
(3)箱线图
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_style(style="darkgrid")
sns.set_context(context="paper")
sns.set_palette("Reds")
df = pd.read_csv("./data/HR.csv")
sns.boxplot(x=df["time_spend_company"], saturation=0.75, whis=3) # 计算异常值时k的取值
plt.show()
(4)折线图
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_style(style="darkgrid")
sns.set_context(context="paper")
sns.set_palette("Reds")
df = pd.read_csv("./data/HR.csv")
#### 第一种方法
sub_df = df.groupby("time_spend_company").mean()
sns.pointplot(sub_df.index, sub_df["left"]) # 横坐标,纵坐标
plt.show()
#### 第二种方法
sns.pointplot(x="time_spend_company", y="left", data=df)
plt.show()
(5)饼图
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_style(style="darkgrid")
sns.set_context(context="paper")
sns.set_palette("Reds")
df = pd.read_csv("./data/HR.csv")
lbs = df["department"].value_counts().index # 设置标签
explodes = [0.1 if i == "sales" else 0 for i in lbs] # 强调
plt.pie(df["department"].value_counts(normalize=True), explode=explodes, labels=lbs, autopct="%1.1f%%",
colors=sns.color_palette("Reds")) # autopct 显示百分比数字
plt.show()
理论
(1)假设检验与方差检验
(2)相关系数:皮尔逊、斯皮尔曼
(3)回归:线性回归
(4)PCA(主成分分析)与奇异值分解
import numpy as np
import scipy.stats as ss
from statsmodels.graphics.api import qqplot
from matplotlib import pyplot as plt
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.decomposition import PCA
norm_dist = ss.norm.rvs(size=20) # 生成符合标准正态分布的20个数字
print(norm_dist)
print(ss.normaltest(norm_dist)) # 检测是否符合正态分布,normaltest是基于偏度和峰度的检验方法
#### NormaltestResult(statistic=0.5846482217637807, pvalue=0.7465265393835774)
#### 统计值为0.58,p值为0.75,若显著性水平定为0.05,p>0.05,假设成立,即符合正态分布
print(ss.chi2_contingency([[15, 95], [85, 5]])) # 卡方检验
#### (126.08080808080808, 2.9521414005078985e-29, 1, array([[55., 55.],[45., 45.]]))
#### (检验统计量,p值,自由度,理论分布)
print(ss.ttest_ind(ss.norm.rvs(size=10), ss.norm.rvs(size=20))) # 独立分布t检验
#### Ttest_indResult(statistic=-1.234591943541198, pvalue=0.2272434915525291)
#### (检验统计量, p值),若显著性水平为0.05,则p > 0.05,假设成立,两个的均值没有差别
print(ss.ttest_ind(ss.norm.rvs(size=100), ss.norm.rvs(size=200))) # 独立分布t检验,数据量增多
#### Ttest_indResult(statistic=1.6229545891329094, pvalue=0.10565647447598514)
print(ss.f_oneway([49, 50, 39, 40, 43], [28, 32, 30, 26, 34], [38, 40, 45, 42, 48])) # 方差检验
#### F_onewayResult(statistic=17.619417475728156, pvalue=0.0002687153079821641)
#### (统计值,p值)
qqplot(ss.norm.rvs(size=100)) # 通过图检验该分布是否为正态分布
plt.show()
s1 = pd.Series([0.1, 0.2, 1.1, 2.4, 1.3, 0.3, 0.5])
s2 = pd.Series([0.5, 0.4, 1.2, 2.5, 1.1, 0.7, 0.1])
print(s1.corr(s2)) # 计算s1和s2的相关系数
#### 0.9333729600465923
print(s1.corr(s2, method="spearman")) # 计算s1和s2的斯皮尔曼相关系数
#### 0.7142857142857144
df = pd.DataFrame([s1, s2]) # pd.DataFrame:针对于列进行相关性计算
print(df.corr())
#### 0 1 2 3 4 5 6
#### 0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0
#### 1 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0
#### 2 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0
#### 3 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0
#### 4 -1.0 -1.0 -1.0 -1.0 1.0 -1.0 1.0
#### 5 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0
#### 6 -1.0 -1.0 -1.0 -1.0 1.0 -1.0 1.0、
df = pd.DataFrame(np.array([s1, s2]).T)
print(df.corr())
#### 0 1
#### 0 1.000000 0.933373
#### 1 0.933373 1.000000
print(df.corr(method="spearman")) # 计算斯皮尔曼相关系数
#### 0 1
#### 0 1.000000 0.714286
#### 1 0.714286 1.000000
x = np.arange(10).astype(np.float_).reshape((10, 1))
y = x * 3 + 4 + np.random.random((10, 1))
reg = LinearRegression() # 构建线性回归
res = reg.fit(x, y) # 拟合过程
y_pred = reg.predict(x) # 预测值
print(y_pred)
print(reg.coef_) # 参数
#### [[3.02021707]]
print(reg.intercept_) # 截距
#### [4.35690495]
data = np.array([np.array([2.5, 0.5, 2.2, 1.9, 3.1, 2.3, 2, 1, 1.5, 1.1]),
np.array([2.4, 0.7, 2.9, 2.2, 3, 2.7, 1.6, 1.1, 1.6, 0.9])]).T
lower_dim = PCA(n_components=1) # 降维,n_components=n,即降为n维,PCA算法用到的是奇异值分解的方法
lower_dim.fit(data)
print(lower_dim.explained_variance_ratio_)
#### [0.96318131]
#### 降维后得到了96%的信息量
print(lower_dim.fit_transform(data)) # 得到转换后的数值
#### [[-0.82797019]
#### [ 1.77758033]
#### [-0.99219749]
#### [-0.27421042]
#### [-1.67580142]
#### [-0.9129491 ]
#### [ 0.09910944]
#### [ 1.14457216]
#### [ 0.43804614]
#### [ 1.22382056]]
import pandas as pd
import numpy as np
from scipy import linalg
#### 自己构造主成分分析降维 ####
def myPCA(data, n_components=100000000):
mean_vals = np.mean(data, axis=0) # 针对列取均值
mid = data - mean_vals
cov_mat = np.cov(mid, rowvar=False) # 若不指定rowvar=False则对行进行协方差计算,应对列进行协方差计算
eig_vals, eig_vects = linalg.eig(np.mat(cov_mat)) # 求协方差矩阵的特征值和特征向量
eig_val_index = np.argsort(eig_vals) # np.argsort()得到排序后的索引,取最大的特征值对应的特征向量
eig_val_inedx = eig_val_index[:-(n_components + 1):-1] # 取最大值的索引
eig_vects = eig_vects[:, eig_val_inedx] # 取出对应的特征向量
low_dim_mat = np.dot(mid, eig_vects) # 进行转换
return low_dim_mat, eig_vals # 返回转化后的特征和特征值
data = np.array([np.array([2.5, 0.5, 2.2, 1.9, 3.1, 2.3, 2, 1, 1.5, 1.1]),
np.array([2.4, 0.7, 2.9, 2.2, 3, 2.7, 1.6, 1.1, 1.6, 0.9])]).T
print(myPCA(data, n_components=1))
复合分析
(1)交叉分析
分析属性和属性之间关系的方法
import pandas as pd
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_context(font_scale=1.5) # 调字体
df = pd.read_csv("./data/HR.csv")
sl_s = df["satisfaction_level"]
le_s = df["last_evaluation"]
np_s = df["number_project"]
amh_s = df["average_monthly_hours"]
tsc_s = df["time_spend_company"]
wa_s = df["Work_accident"]
l_s = df["left"]
pl5_s = df["promotion_last_5years"]
s_s = df["salary"]
d_s = df["department"]
#### 去除异常值
df = df.dropna(axis=0, how="any") # 去除空值,axis指定坐标轴,0为横坐标,1为纵坐标,how="all"这一行全是空值时才去掉 how="any"这一行有一个空值就去掉
df = df[le_s <= 1][s_s != "nme"][d_s != "sale"] # 去除异常值
#### 交叉分析 ####
#### 各个部门的离职率之间是否有明显差异,使用独立t检验方法 ####
#### 基本思路:得到各个部门的离职分布,两两间求t检验统计量,并求出p值,目的是得到各个部门的离职分布 ####
dp_indices = df.groupby(by="department").indices # indices属性可以得到分组后的索引
sales_values = df["left"].iloc[dp_indices["sales"]].values
technical_values = df["left"].iloc[dp_indices["technical"]].values
print(ss.ttest_ind(sales_values, technical_values)) # 打印t统计量和p值
dp_keys = list(dp_indices.keys()) # 必须用list()进行转化
dp_t_mat = np.zeros([len(dp_keys), len(dp_keys)])
for i in range(len(dp_keys)):
for j in range(len(dp_keys)):
p_value = ss.ttest_ind(df["left"].iloc[dp_indices[dp_keys[i]]].values,
df["left"].iloc[dp_indices[dp_keys[j]]].values)[1] # 索引取1时,只打印p值
if p_value < 0.05:
dp_t_mat[i][j] = 1
else:
dp_t_mat[i][j] = p_value
sns.heatmap(dp_t_mat, xticklabels=dp_keys, yticklabels=dp_keys) # 颜色越深,说明部门之间的离职率有显著差异;颜色越浅,说明部门之间的离职率没有显著差异
plt.show()
#### 通过透视表进行交叉分析 ####
piv_tb = pd.pivot_table(df, values="left", index=["promotion_last_5years", "salary"],
columns=["Work_accident"], aggfunc=np.mean) # index横坐标, columns纵坐标,aggfunc聚合方法
print(piv_tb)
sns.heatmap(piv_tb, vmin=0, vmax=1, cmap=sns.color_palette("Reds", n_colors=256))
plt.show()
(2)分组与钻取
分组分析(一般要结合其他分析方法进行配合使用)
钻取(分组分析最常用到的分析手段)
import pandas as pd
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_context(font_scale=1.5)
df = pd.read_csv("./data/HR.csv")
sl_s = df["satisfaction_level"]
le_s = df["last_evaluation"]
np_s = df["number_project"]
amh_s = df["average_monthly_hours"]
tsc_s = df["time_spend_company"]
wa_s = df["Work_accident"]
l_s = df["left"]
pl5_s = df["promotion_last_5years"]
s_s = df["salary"]
d_s = df["department"]
#### 去除异常值
df = df.dropna(axis=0, how="any") # 去除空值,axis指定坐标轴,0为横坐标,1为纵坐标,how="all"这一行全是空值时才去掉 how="any"这一行有一个空值就去掉
df = df[le_s <= 1][s_s != "nme"][d_s != "sale"] # 去除异常值
#### 通过绘制柱状图,直观了解分组情况 ####
# sns.barplot(x="salary", y="left", hue="department", data=df) # hue:向下根据部门钻取
# plt.show()
#### 连续值 ####
sll_s = df["satisfaction_level"]
sns.barplot(list(range(len(sll_s))), sll_s.sort_values()) # 根据值进行排序
plt.show() # 需要等较长的一段时间,长到会以为可能出问题了
(3)相关分析
衡量两组数据分布趋势或者变化趋势大小的分析方法,用相关系数直接衡量相关性的大小。
相关系数:pearson相关系数,spearman相关系数
import pandas as pd
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_context(font_scale=1.5)
df = pd.read_csv("./data/HR.csv")
sl_s = df["satisfaction_level"]
le_s = df["last_evaluation"]
np_s = df["number_project"]
amh_s = df["average_monthly_hours"]
tsc_s = df["time_spend_company"]
wa_s = df["Work_accident"]
l_s = df["left"]
pl5_s = df["promotion_last_5years"]
s_s = df["salary"]
d_s = df["department"]
#### 去除异常值 ####
df = df.dropna(axis=0, how="any") # 去除空值,axis指定坐标轴,0为横坐标,1为纵坐标,how="all"这一行全是空值时才去掉 how="any"这一行有一个空值就去掉
df = df[le_s <= 1][s_s != "nme"][d_s != "sale"] # 去除异常值
#### 计算相关系数 ####
sns.heatmap(df.corr(), vmin=-1, vmax=1, cmap=sns.color_palette("RdBu", n_colors=128)) # df.corr():计算相关系数,去掉离散值
plt.show()
离散属性相关性系数的计算
import pandas as pd
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import seaborn as sns
import math
sns.set_context(font_scale=1.5)
#### 计算离散值的相关系数 ####
s1 = pd.Series(["X1", "X1", "X2", "X2", "X2", "X2"])
s2 = pd.Series(["Y1", "Y1", "Y1", "Y2", "Y2", "Y2"])
def getEntropy(s): # 熵
if not isinstance(s, pd.core.series.Series): # 判断是否是series,若不是则转化为series
s = pd.Series(s)
prt_ary = s.groupby(by=s).count().values/float(len(s)) # 计算分布,得到概率分布
return -(np.log2(prt_ary) * prt_ary).sum() # 根据公式求和计算熵
print("Entropy", getEntropy(s1))
#### Entropy 0.9182958340544896
print("Entropy", getEntropy(s2))
#### Entropy 1.0
#### 0.5和0.5的分布
def getCondEntropy(s1, s2): # 条件熵
d = dict() # 创建一个新的字典
for i in list(range(len(s1))): # 先求出s1的分布
d[s1[i]] = d.get(s1[i], []) + [s2[i]] # 记录s1的值下,s2的分布
return sum([getEntropy(d[k])*len(d[k])/float(len(s1)) for k in d])
print("CondEntropy", getCondEntropy(s1, s2))
#### CondEntropy 0.5408520829727552
print("CondEntropy", getCondEntropy(s2, s1))
#### CondEntropy 0.4591479170272448 条件熵是不对称的
def getEntropyGain(s1, s2): # 熵增益
return getEntropy(s2) - getCondEntropy(s1, s2)
print("EntropyGain",getEntropyGain(s1, s2))
#### EntropyGain 0.4591479170272448
print("EntropyGain",getEntropyGain(s2, s1))
#### EntropyGain 0.4591479170272448 熵增益是对称的
def getEntropyGainRatio(s1, s2): # 熵增益率
return getEntropyGain(s1, s2)/getEntropy(s2)
print("EntropyGainRatio", getEntropyGainRatio(s1, s2))
#### EntropyGainRatio 0.4591479170272448
print("EntropyGainRatio", getEntropyGainRatio(s2, s1))
#### EntropyGainRatio 0.5 熵增益率不是对称的
def getDiscreteCorr(s1, s2): # 衡量离散值的相关性
return getEntropyGain(s1, s2)/math.sqrt(getEntropy(s1) * getEntropy(s2))
print('DiscreteCorr', getDiscreteCorr(s1, s2))
#### DiscreteCorr 0.4791387674918639
print('DiscreteCorr', getDiscreteCorr(s2, s1))
#### DiscreteCorr 0.4791387674918639 对称
def getProbSS(s): # 求概率平方和的函数
if not isinstance(s, pd.core.series.Series): # 判断是否是series,若不是则转化为series
s = pd.Series(s)
prt_ary = s.groupby(by=s).count().values/float(len(s)) # 计算分布,得到概率分布
return sum(prt_ary**2)
def getGini(s1, s2): # 求Gini系数
d = dict() # 创建一个新的字典
for i in list(range(len(s1))): # 先求出s1的分布
d[s1[i]] = d.get(s1[i], []) + [s2[i]] # 记录s1的值下,s2的分布
return 1 - sum([getProbSS(d[k]) * len(d[k])/float(len(s1)) for k in d])
print("Gini", getGini(s1, s2))
#### Gini 0.25
print("Gini", getGini(s2, s1))
#### Gini 0.2222222222222222 Gini系数不对称
(4)因子分析(成分分析)
从多个属性变量中分析共性,相关因子的方法
分为探索性因子分析和验证性因子分析
import pandas as pd
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.decomposition import PCA
sns.set_context(font_scale=1.5)
df = pd.read_csv("./data/HR.csv")
sl_s = df["satisfaction_level"]
le_s = df["last_evaluation"]
np_s = df["number_project"]
amh_s = df["average_monthly_hours"]
tsc_s = df["time_spend_company"]
wa_s = df["Work_accident"]
l_s = df["left"]
pl5_s = df["promotion_last_5years"]
s_s = df["salary"]
d_s = df["department"]
#### 去除异常值 ####
df = df.dropna(axis=0, how="any") # 去除空值,axis指定坐标轴,0为横坐标,1为纵坐标,how="all"这一行全是空值时才去掉 how="any"这一行有一个空值就去掉
df = df[le_s <= 1][s_s != "nme"][d_s != "sale"] # 去除异常值
my_pca = PCA(n_components=7) # 共7个属性
lower_mat = my_pca.fit_transform(df.drop(labels=["salary", "department", "left"], axis=1)) # 数据表中不允许出现离散数据
print("Ratio:", my_pca.explained_variance_ratio_)
#### Ratio: [9.98565340e-01 8.69246970e-04 4.73865973e-04 4.96932182e-05
#### 2.43172315e-05 9.29496619e-06 8.24128218e-06] # 9.98565340e-01只有这个结果接近于1,其他结果都较小,故通过主成分分析后,需要保留的因子只有这一个
sns.heatmap(pd.DataFrame(lower_mat).corr(), vmin=-1, vmax=1, cmap=sns.color_palette("RdBu", n_colors=128))
plt.show()
(5)聚类分析
(6)回归分析
总结
数据类型 | 可用方法 |
---|---|
连续—连续 | 相关系数,假设检验 |
连续—离散(二值) | 相关系数,连续二值化(最小Gini切分,最大熵增益切分) |
连续—离散(非二值) | 相关系数(定序) |
离散(二值)—离散(二值) | 相关系数,熵相关,F分值 |
离散—离散(非二值) | 熵相关,Gini,相关系数(定序) |
特征工程概述
(1)数据和特征决定了机器学习的上限,模型和算法只是逼近这个上限
(2)特征工程一般包括特征使用,特征获取,特征处理,特征监控四个方面
数据清洗
(1)数据样本抽样
(2)异常值(空值)处理
import numpy as np
import pandas as pd
df = pd.DataFrame({
"A": ["a0", "a1", "a1", "a2", "a3", "a4"], "B": ["b0", "b1", "b2", "b2", "b3", None],
"C": [1, 2, None, 3, 4, 5], "D": [0.1, 10.2, 11.4, 8.9, 9.1, 12], "E": [10, 19, 32, 25, 8, None],
"F": ["f0", "f1", "g2", "f3", "f4", "f5"]})
print(df)
#### A B C D E F
#### 0 a0 b0 1.0 0.1 10.0 f0
#### 1 a1 b1 2.0 10.2 19.0 f1
#### 2 a1 b2 NaN 11.4 32.0 g2
#### 3 a2 b2 3.0 8.9 25.0 f3
#### 4 a3 b3 4.0 9.1 8.0 f4
#### 5 a4 None 5.0 12.0 NaN f5
#### NaN:not a number
print(df.isnull())
#### A B C D E F
#### 0 False False False False False False
#### 1 False False False False False False
#### 2 False False True False False False
#### 3 False False False False False False
#### 4 False False False False False False
#### 5 False True False False True False
#### 去掉所有空值 ####
df_1 = df.dropna()
print(df_1)
#### A B C D E F
#### 0 a0 b0 1.0 0.1 10.0 f0
#### 1 a1 b1 2.0 10.2 19.0 f1
#### 3 a2 b2 3.0 8.9 25.0 f3
#### 4 a3 b3 4.0 9.1 8.0 f4
#### 有空值的行都被去掉了
#### 去掉某一行的空值 ####
df_2 = df.dropna(subset=["B"])
print(df_2)
#### A B C D E F
#### 0 a0 b0 1.0 0.1 10.0 f0
#### 1 a1 b1 2.0 10.2 19.0 f1
#### 2 a1 b2 NaN 11.4 32.0 g2
#### 3 a2 b2 3.0 8.9 25.0 f3
#### 4 a3 b3 4.0 9.1 8.0 f4
#### 只去掉B的空值
#### 识别重复值 ####
df_3 = df.duplicated(["A"]) # A中重复的元素
print(df_3)
#### 0 False
#### 1 False
#### 2 True
#### 3 False
#### 4 False
#### 5 False
#### dtype: bool
df_4 = df.duplicated(["A", "B"]) # 必须A和B中都为重复的,才显示True
print(df_4)
#### 0 False
#### 1 False
#### 2 False
#### 3 False
#### 4 False
#### 5 False
#### dtype: bool
#### 去掉重复值 ####
df_5 = df.drop_duplicates(["A"]) # 去掉A中的重复值
print(df_5)
#### A B C D E F
#### 0 a0 b0 1.0 0.1 10.0 f0
#### 1 a1 b1 2.0 10.2 19.0 f1
#### 3 a2 b2 3.0 8.9 25.0 f3
#### 4 a3 b3 4.0 9.1 8.0 f4
#### 5 a4 None 5.0 12.0 NaN f5
df_6 = df.drop_duplicates(["A"], keep="first") # keep参数表示保留哪一个,first, last, false(去掉所有的重复行),inplace参数为True是,原始的df会发生变化
print(df_6)
#### A B C D E F
#### 0 a0 b0 1.0 0.1 10.0 f0
#### 1 a1 b1 2.0 10.2 19.0 f1
#### 3 a2 b2 3.0 8.9 25.0 f3
#### 4 a3 b3 4.0 9.1 8.0 f4
#### 5 a4 None 5.0 12.0 NaN f5
#### 异常值标注 ####
df_7 = df["B"].fillna("b*") # 将B中的异常值标注为b*
print(df_7)
#### 0 b0
#### 1 b1
#### 2 b2
#### 3 b2
#### 4 b3
#### 5 b*
#### Name: B, dtype: object
#### 集中值指代 ####
df_8 = df["E"].fillna(df["E"].mean()) # 用E的均值替换E中的异常值,求E的均值的时候,自动忽略E中的异常值
print(df_8)
#### 0 10.0
#### 1 19.0
#### 2 32.0
#### 3 25.0
#### 4 8.0
#### 5 18.8
#### Name: E, dtype: float64
#### 插值 ####
df_9 = df["E"].interpolate() # 插值的方法只能用于Series
print(df_9)
#### 0 10.0
#### 1 19.0
#### 2 32.0
#### 3 25.0
#### 4 8.0
#### 5 8.0
#### Name: E, dtype: float64
#### 如果在末尾,则取前面那个数的值,在开头则取后面那个数的值
print(pd.Series([1, None, 4, 5, 20]).interpolate())
#### 0 1.0
#### 1 2.5
#### 2 4.0
#### 3 5.0
#### 4 20.0
#### dtype: float64
#### 取的是相邻两个值的平均值
#### 过滤异常值 ####
upper_q = df["D"].quantile(0.75) # 上四分位数
lower_q = df["D"].quantile(0.25) # 下四分位数
q_int = upper_q - lower_q
k = 1.5
df_10 = df[df["D"] > lower_q - k * q_int][df["D"] < upper_q + k * q_int]
print(df_10)
#### A B C D E F
#### 1 a1 b1 2.0 10.2 19.0 f1
#### 2 a1 b2 NaN 11.4 32.0 g2
#### 3 a2 b2 3.0 8.9 25.0 f3
#### 4 a3 b3 4.0 9.1 8.0 f4
#### 5 a4 None 5.0 12.0 NaN f5
df_11 = df.drop(2) # 去掉第二行
print(df_11)
#### A B C D E F
#### 0 a0 b0 1.0 0.1 10.0 f0
#### 1 a1 b1 2.0 10.2 19.0 f1
#### 3 a2 b2 3.0 8.9 25.0 f3
#### 4 a3 b3 4.0 9.1 8.0 f4
#### 5 a4 None 5.0 12.0 NaN f5
df_12 = df[[True if item.startswith("f") else False for item in list(df["F"].values)]] # 过滤掉F中不是f开头的行
print(df_12)
#### A B C D E F
#### 0 a0 b0 1.0 0.1 10.0 f0
#### 1 a1 b1 2.0 10.2 19.0 f1
#### 3 a2 b2 3.0 8.9 25.0 f3
#### 4 a3 b3 4.0 9.1 8.0 f4
#### 5 a4 None 5.0 12.0 NaN f5
特征预处理
(1)标注(标记、标签、label)
(2)特征预处理主要内容
文章浏览阅读122次。16、interface中的成员变量默认为public static final类型,方法只能是public(默认为public)17、内部类访问外部类成员:Outer.this.num;18、一道有趣的题目 使用内部类实现该程序。(答案附在本文末尾)interface Inter { void show();}clas..._public
文章浏览阅读1k次。智慧交通正在成为新基建的主力军,伴随着新能源汽车和汽车融入智能制造产业链的结构性深化,智慧交通产业构架成为中国经济发展进入新常态下融入碳中和、碳达峰的绿色发展和以新基建为代表的的中国智能制..._智能交通 智慧交通 芯片
文章浏览阅读1.4k次。阿里云服务器在docker上部署MySQL(图文详细教程)设置容器、运行容情做数据挂载、端口映射、目录映射。_阿里云服务器docker安装数据库
文章浏览阅读1.5k次。描述在线性代数、计算几何中,向量点积是一种十分重要的运算。给定两个n维向量a=(a1,a2,…,an)和b=(b1,b2,…,bn),求点积a·b=a1b1+a2b2+…+anbn。输入第一行是一个整数n。1 <= n <= 1000。第二行包含n个整数a1,a2,…,an。第三行包含n个整数b1,b2,…,bn。相邻整数之间用单个空格隔开。输出一个整数,即两个向量的点积结果。样例输入31 4 62 1 5样例输出36n = int(input())s = li_python 给定两个n维向量a=(a1,a2,...,an)和b=(b1,b2,...,bn),求点积a·b=a1b1+a2b
文章浏览阅读3.8k次。描述输入三个整数或小数,输出它们的和如果结果是整数,就保留小数点后面一位的0(用python写则不用特别处理,程序自然会如此)输入输入三个整数或小数输出和样例输入1 2.3 4.7样例输出8.0代码:s = input().split()a = float(s[0])b = float(s[1])c = float(s[2])print(a+b+c)..._python如果三个数全部是整数,则结果也是整数。如果三个数中有小数,则结果
文章浏览阅读627次。//////////////转载:雷神博客http://blog.csdn.net/leixiaohua1020/article/details/40525591/////////////本文记录SDL播放视频的技术。在这里使用的版本是SDL2。实际上SDL本身并不提供视音频播放的功能,它只是封装了视音频播放的底层API。在Windows平台下,SDL封装了Direct3D_用c语言调用sdl2播放yuv
文章浏览阅读999次。Activity页public class MainActivity extends AppCompatActivity { private ListView mlv1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);_zy-2021-10-21-0119
文章浏览阅读1.6k次。1,动态设置事件: function F1(){ alert('In F1'); } function F2{ alert(In F2); }_javascript curtd
文章浏览阅读685次。R语言ggplot2可视化:使用ggplot2可视化散点图、使用labs参数自定义X轴的轴标签文本(customize X axis labels)_r语言中的labs()的用法
文章浏览阅读4.1k次。今天讨论班一个师姐讲到L1 norm还有L2 norm 的regularization问题,还有晚上和一个同学也讨论到这个问题,具体什么时候用L1,什么时候用L2,论文上写道一般当成分中有几个成分是principal factor的时候我们会使用L1 norm penalty,但是为什么L1会有这个效果。一个网上的讨论:http://www.quora.com/Machine-Lear_the differences between l1 snd l2
文章浏览阅读8.7k次,点赞13次,收藏40次。类的继承结构中,越往上的类越具有通用性,也就越抽象。当它抽象到一定程度,就变成概念成框架,不能再产生实例化的对象了。例如“交通工具”,就无法用它来产生一个实例。对应这一现象,Java中提供了抽象类,它只能作为父类,不能实例化。定义抽象类的作用是将一类对象的共同特点抽象出来,成为代表该类共同特性的抽象概念,其后在描述某一具体对象时,只要添加与其他子类对象的不同之处,而不需要重复类的共同特性。这样就使得程序概念层次分明,开发更高效。与抽象类紧密相连的是抽象方法一它总是用在抽象类或接口中。_抽象方法怎么定义
文章浏览阅读2.0k次。从海外客户端Bidding看,移动开发者应如何应对竞价模式变化2021年,对于渴望通过广告进行变现的移动开发者来说,可能注定是风云变幻的一年,也将是移动互联网广告程序化购买这个行业程碑式的一年,对此很多国内出海开发者会有更早的感触。自2020年三四季度始,大洋彼岸的美国就掀起了一轮“移动流量的客户端竞价革命”。其实,对于流量竞价(Realtime Bidding)很多PC时代的开发者并不陌生,简而言之,流量竞价就是APP的每一次广告曝光的机会都可以分发至多个买方平台,比如DS、Adnetwork_admob竞价和瀑布的区别和文档