目录
一、数据统计
1、行列式的最大元素和最小元素
2、求向量的平均值和中值
3、对矩阵做排序
二、数据优化(数据残缺值和异常值的处理)
1、数据残缺
①插值
②拟合
③邻近替换
④KNN算法填充
2、数据异常
①拉依达准则
②替换异常值
3、数据变换
①0-1标准化
②z-score标准化
③标准化的应用
4、数据离散化
①等宽法
②等频法
三、数据降维
1、主成分分析
①主成分分析简介
②主成分分析计算步骤
③案例分析
数据统计一般包括求矩阵最大、最小元素,求矩阵平均值和中值, 矩阵元素求和、求积,矩阵元素累加和与累乘积,求标准方差、相关系数、元素排序等。
直接举例子说明
命令如下:
A=[12,45,58;25,60,-45;56,25,178;2,0,-13];
max(A,[],2) %求每行最大元素
ans =
58
60
178
2
max(A) %求每列最大元素
ans =
56 60 178
min(min(A)) %求整个矩阵的最小元素。也可用命令:min(A(:))
ans =
-45
命令如下:
x=[10,24,6,-8,0,-12]; %偶数个元素
mean(x) %求此向量的平均值
x =
10 24 6 -8 0 -12
ans =
3.3333
median(x) %求此向量的中值
ans =
3
命令如下:
A=[0,-11,5;1,15,7;16,9,-20];
sort(A) %对A的每列按升序排序
ans =
0 -11 -20
1 9 5
16 15 7
-sort(-A,2) %对A的每行按降序排列
ans =
5 0 -11
15 7 1
16 9 -20
[X,I]=sort(A) %对A按列排序,并将每个元素所在行号送矩阵I
X =
0 -11 -20
1 9 5
16 15 7
I =
1 1 3
2 3 1
3 2 2
插值和拟合都是数据优化的一种方法,当实验数据不够多时经常需要用到这种方法来画图。在MATLAB中都有特定的函数来完成这些功能。这两种方法的确别在于:
当测量值是准确的,没有误差时,一般用插值;
当测量值与真实值有误差时,一般用数据拟合。
对于一维曲线的插值,一般用到的函数yi=interp1(X,Y,xi,method) ,其中method包括nearst,linear,spline,cubic。
对于二维曲面的插值,一般用到的函数zi=interp2(X,Y,Z,xi,yi,method),其中method也和上面一样,常用的是cubic。
%产生原始数据
x=0:0.1:1;
y=(x.^2-3*x+7).*exp(-4*x).*sin(2*x);
subplot(2,2,1);
plot(x,y);
title('原始数据');
%线性插值
xx=0:0.01:1;
y1=interp1(x,y,xx,'linear');
%subplot(2,2,1)
%plot(x,y,'o',xx,y1);
%title('线性插值');
%最邻近点插值
y2=interp1(x,y,xx,'nearest');
subplot(2,2,2)
plot(x,y,'o',xx,y2);
title('最邻近点插值');
%三次插值
y3=interp1(x,y,xx,'pchip');
subplot(2,2,3)
plot(x,y,'o',xx,y3);
title('三次插值');
%三次样条插值
y4=interp1(x,y,xx,'spline');
subplot(2,2,4)
plot(x,y,'o',xx,y4);
title('三次样条插值');
经典问题:利用给定的高度补充地图
%插值基点为网格节点
clear all
y=20:-1:0;
x=0:20;
z=[0.2 0.2 0.2 0.2 0.2 0.2 0.4 0.4 0.3 0.2 0.3 0.2 0.1 0.2 0.2 0.4 0.3 0.2 0.2 0.2 0.2;
0.3 0.2 0.2 0.2 0.2 0.4 0.3 0.3 0.3 0.3 0.4 0.2 0.2 0.2 0.2 0.4 0.4 0.4 0.3 0.2 0.2;
0.2 0.3 0.3 0.2 0.3 1 0.4 0.5 0.3 0.3 0.3 0.3 0.2 0.2 0.2 0.6 0.5 0.4 0.4 0.2 0.2;
0.2 0.2 0.4 0.2 1 1.1 0.9 0.4 0.3 0.3 0.5 0.3 0.2 0.2 0.2 0.7 0.3 0.6 0.6 0.3 0.4;
0.2 0.2 0.9 0.7 1 1 1 0.7 0.5 0.3 0.2 0.2 0.2 0.6 0.2 0.8 0.7 0.9 0.5 0.5 0.4;
0.2 0.3 1 1 1 1.2 1 1.1 0.8 0.3 0.2 0.2 0.2 0.5 0.3 0.6 0.6 0.8 0.7 0.6 0.5;
0.2 0.4 1 1 1.1 1.1 1.1 1.1 0.6 0.3 0.4 0.4 0.2 0.7 0.5 0.9 0.7 0.4 0.9 0.8 0.3;
0.2 0.2 0.9 1.1 1.2 1.2 1.1 1.1 0.6 0.3 0.5 0.3 0.2 0.4 0.3 0.7 1 0.7 1.2 0.8 0.4;
0.2 0.3 0.4 0.9 1.1 1 1.1 1.1 0.7 0.4 0.4 0.4 0.3 0.5 0.5 0.8 1.1 0.8 1.1 0.9 0.3;
0.3 0.3 0.5 1.2 1.2 1.1 1 1.2 0.9 0.5 0.6 0.4 0.6 0.6 0.3 0.6 1.2 0.8 1 0.8 0.5;
0.3 0.5 0.9 1.1 1.1 1 1.2 1 0.8 0.7 0.5 0.6 0.4 0.5 0.4 1 1.3 0.9 0.9 1 0.8;
0.3 0.5 0.6 1.1 1.2 1 1 1.1 0.9 0.4 0.4 0.5 0.5 0.8 0.6 0.9 1 0.5 0.8 0.8 0.9;
0.4 0.5 0.4 1 1.1 1.2 1 0.9 0.7 0.5 0.6 0.3 0.6 0.4 0.6 1 1 0.6 0.9 1 0.7;
0.3 0.5 0.8 1.1 1.1 1 0.8 0.7 0.7 0.4 0.5 0.4 0.4 0.5 0.4 1.1 1.3 0.7 1 0.7 0.6;
0.3 0.5 0.9 1.1 1 0.7 0.7 0.4 0.6 0.4 0.4 0.3 0.5 0.5 0.3 0.9 1.2 0.8 1 0.8 0.4;
0.2 0.3 0.6 0.9 0.8 0.8 0.6 0.3 0.4 0.5 0.4 0.5 0.4 0.2 0.5 0.5 1.3 0.6 1 0.9 0.3;
0.2 0.3 0.3 0.7 0.6 0.6 0.4 0.2 0.3 0.5 0.8 0.8 0.3 0.2 0.2 0.8 1.3 0.9 0.8 0.8 0.4;
0.2 0.3 0.3 0.6 0.3 0.4 0.3 0.2 0.2 0.3 0.6 0.4 0.3 0.2 0.4 0.3 0.8 0.6 0.7 0.4 0.4;
0.2 0.3 0.4 0.4 0.2 0.2 0.2 0.3 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.5 0.7 0.4 0.4 0.3 0.3;
0.2 0.2 0.3 0.2 0.2 0.3 0.2 0.2 0.2 0.2 0.2 0.1 0.2 0.4 0.3 0.6 0.5 0.3 0.3 0.3 0.2;
0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.4 0.7 0.4 0.2 0.4 0.5 0.5];
%未插值直接画图
figure(1) %创建图形窗口1,并激活
surf(x,y,z);
shading flat %用shading flat命令,使曲面变的光滑
title('未插值地形图')
xlabel('横坐标')
ylabel('纵坐标')
zlabel('高度')
%三次插值后画图
%画地形图
figure(2)
xi=0:0.05:20;
yi=20:-0.05:0;
zi=interp2(x,y,z,xi',yi,'cubic'); %'cubic'三次插值
surfc(xi,yi,zi); %底面带等高线
shading flat
title('插值后地形图')
xlabel('横坐标')
ylabel('纵坐标')
zlabel('高度')
%画立体等高线图
figure(3)
contour3(xi,yi,zi);
title('立体等高线图')
xlabel('横坐标')
ylabel('纵坐标')
zlabel('高度')
%画等高线图
figure(4)
[c,h]=contour(xi,yi,zi);
clabel(c,h); %用于为2维等高线添加标签
colormap cool %冷色调
title('平面等高线图')
xlabel('横坐标')
ylabel('纵坐标')
对于一维曲线的拟合,一般用到的函数p=polyfit(x,y,n)和yi=polyval(p,xi),这个是最常用的最小二乘法的拟合方法。
对于二维曲面的拟合,有很多方法可以实现,这里运用Spline Toolbox里面的函数功能。
x = 0:0.1:1;
y = [-0.447 1.978 3.28 6.16 7.08 7.34 7.66 9.56 9.48 9.30 11.2];
A = polyfit(x,y,2) %A为拟合出来的函数
z = polyval(A,x); %求多项式在x处的值z
plot(x,y,'k+',x,z,'r')
前/后一个非缺失值将其替换
最近的非缺失值替换
相邻的非离群值线性插值填充
test_data1=fillmissing(test_data,'previous');
test_data1=fillmissing(test_data,'next');
test_data1=fillmissing(test_data,'nearest');
test_data1=fillmissing(test_data,'linear');
from sklearn.metrics import nan_euclidean_distances
import numpy as np
from sklearn.impute import KNNImputer
X = [[1, 2, np.nan], [3, 4, 3], [np.nan, 6, 5], [8, 8, 7]]
# python的nan_euclidean_distances函数可计算含空值的距离矩阵
nan_euclidean_distances(X, X)
# python用KNNImputer进行空值填充
X = [[1, 2, np.nan], [3, 4, 3], [np.nan, 6, 5], [8, 8, 7]]
imputer = KNNImputer(n_neighbors=2)
a = imputer.fit_transform(X)
print(a)
拉依达准则是用来发现数据异常值
x=[1, 1.1, 1.2, 1.3, 1.4, 2, 1.2, 1.3, 1.5, 0.9, 0.8, 1.1, 11];
inlier = [];outlier = [];
len = length(x);
average1 = mean(x); % x中所有元素的均值
standard1 = std(x); % x的标准差
for i = 1:len % 遍历x向量,判断是否为偏离点,不是偏离点则存入inline
if abs(x(i)-average1)= standard2*3
outlier = [outlier x(i)];
end
end
替换方法跟缺失值的替换一致,我们可以直接将其看作缺失值进行处理,替换方法如上。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# matplotlib inline
# 数据标准化
# (1)0-1标准化
df = pd.DataFrame({"value1":np.random.rand(10)*20,
'value2':np.random.rand(10)*100})
print(df.head())
print('------')
# 创建数据
def data_norm(df,*cols):
df_n = df.copy()
for col in cols:
ma = df_n[col].max()
mi = df_n[col].min()
df_n[col + '_n'] = (df_n[col] - mi) / (ma - mi)
return(df_n)
# 创建函数,标准化数据
df_n = data_norm(df, 'value1', 'value2')
print(df_n.head())#标准化数据
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({"value1": np.random.rand(10) * 100,
'value2': np.random.rand(10) * 100})
print(df.head())
print('------')
# 创建数据
def data_Znorm(df, *cols):
df_n = df.copy()
for col in cols:
u = df_n[col].mean()
std = df_n[col].std()
df_n[col + '_Zn'] = (df_n[col] - u) / std # 平均值/标准差
return (df_n)
# 创建函数,标准化数据
df_z = data_Znorm(df, 'value1', 'value2')
u_z = df_z['value1_Zn'].mean()
std_z = df_z['value1_Zn'].std()
print(df_z)
print('标准化后value1的均值为:%.2f, 标准差为:%.2f' % (u_z, std_z))
# 标准化数据
# 经过处理的数据符合标准正态分布,即均值为0,标准差为1
# 什么情况用Z-score标准化:
# 在分类、聚类算法中,需要使用距离来度量相似性的时候,Z-score表现更好
# 八类产品的两个指标value1,value2,其中value1权重为0.6,value2权重为0.4
# 通过0-1标准化,判断哪个产品综合指标状况最好
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({"value1": np.random.rand(10) * 30,
'value2': np.random.rand(10) * 100},
index=list('ABCDEFGHIJ'))
# print(df.head())
# print('------')
# 创建数据"
def data_norm(df, *cols):
df_n = df.copy()
for col in cols:
ma = df_n[col].max()
mi = df_n[col].min()
df_n[col + '_n'] = (df_n[col] - mi) / (ma - mi)
return df_n
df_n1 = data_norm(df, 'value1', 'value2')
# 进行标准化处理
df_n1['f'] = df_n1['value1_n'] * 0.6 + df_n1['value2_n'] * 0.4
df_n1.sort_values(by='f', inplace=True, ascending=False)
df_n1['f'].plot(kind='line', style='--.k', alpha=0.8, grid=True)
print(df_n1)
# 查看综合指标状况
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 等宽法 → cut方法
ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
# 有一组人员年龄数据,希望将这些数据划分为“18到25”,“26到35”,“36到60”,“60以上”几个面元,分成4个区间。
bins = [18, 25, 35, 60, 100]
cats = pd.cut(ages, bins)
print(cats)
print(type(cats))
print('____')
print(cats.codes, type(cats.codes)) # 0-3对应分组后的四个区间,用代号来注释数据对应区间,结果为ndarray;可以查看里边的等级
print(cats.categories, type(cats.categories)) # 四个区间,结果为index
print(pd.value_counts(cats)) # 按照区间计数
print('-------')
# cut结果含有一个表示不同分类名称的层级数组以及一个年龄数据进行标号的代号属性
print(pd.cut(ages, [18, 26, 36, 61, 100], right=False))
print('-------')
# 通过right函数修改闭端,默认为True
group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
print(pd.cut(ages, bins, labels=group_names))
print('-------')
# 可以设置自己的区间名称,用labels参数
df = pd.DataFrame({'ages': ages})
group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
s = pd.cut(df['ages'], bins) # 也可以 pd.cut(df['ages'],5),将数据等分为5份
df['label'] = s
cut_counts = s.value_counts(sort=False)
print(df)
print(cut_counts)
# 对一个Dataframe数据进行离散化,并计算各个区间的数据计数
plt.scatter(df.index, df['ages'], cmap='Reds', c=cats.codes)
plt.grid()
# 用散点图表示,其中颜色按照codes分类
# 注意codes是来自于Categorical对象
# 等频法 → qcut方法
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
data = np.random.randn(1000)
s = pd.Series(data)
cats = pd.qcut(s,4) # 按四分位数进行切割,可以试试 pd.qcut(data,10)
print(cats.head())
print(pd.value_counts(cats))
print('------')
# qcut → 根据样本分位数对数据进行面元划分,得到大小基本相等的面元,但并不能保证每个面元含有相同数据个数
# 也可以设置自定义的分位数(0到1之间的数值,包含端点) → pd.qcut(data1,[0,0.1,0.5,0.9,1])
plt.scatter(s.index,s,cmap = 'Greens',c = pd.qcut(data,4).codes)
plt.xlim([0,1000])
plt.grid()
# 用散点图表示,其中颜色按照codes分类
# 注意codes是来自于Categorical对象
主成分分析是一种降维算法,它能将多个指标转换为少数几个主成分,这些主成分是原始变量的线性组合,且彼此之间互不相关,其能反映出原始数据的大部分信息。一般来说,当研究的问题涉及到多变量且变量之间存在很强的相关性时,我们可考虑使用主成分分析的方法来对数据进行简化。
标准化处理
计算标准化样本的协方差矩阵
计算R的特征值和特征向量
计算主成分贡献率以及累计贡献率
写出主成分
根据系数分析主成分代表的意义
主成分分析指标解释案例
主成分分析的一大难点是指标意义模糊,难以解释,下面这个例子可以辅助理解。
上表的累计贡献率 = 当前项贡献率 + 之前的累计贡献率。当累计贡献率 > 80%时,剩下的特征向量可以舍弃。
上面的分析需要一定的语言组织能力,也需要一定运气成分,若难以解释,或者强行解释,或者换方法。
案例参考文章:原文链接:https://blog.csdn.net/qq1198768105/article/details/119898545
clear;clc
% load data1.mat % 主成分聚类
load data2.mat % 主成分回归
[n,p] = size(x); % n是样本个数,p是指标个数
%% 第一步:对数据x标准化为X
X=zscore(x); % matlab内置的标准化函数(x-mean(x))/std(x)
%% 第二步:计算样本协方差矩阵
R = cov(X);
%% 注意:以上两步可合并为下面一步:直接计算样本相关系数矩阵
R = corrcoef(x);
disp('样本相关系数矩阵为:')
disp(R)
%% 第三步:计算R的特征值和特征向量
% 注意:R是半正定矩阵,所以其特征值不为负数
% R同时是对称矩阵,Matlab计算对称矩阵时,会将特征值按照从小到大排列哦
% eig函数的详解见第一讲层次分析法的视频
[V,D] = eig(R); % V 特征向量矩阵 D 特征值构成的对角矩阵
%% 第四步:计算主成分贡献率和累计贡献率
lambda = diag(D); % diag函数用于得到一个矩阵的主对角线元素值(返回的是列向量)
lambda = lambda(end:-1:1); % 因为lambda向量是从小大到排序的,我们将其调个头
contribution_rate = lambda / sum(lambda); % 计算贡献率
cum_contribution_rate = cumsum(lambda)/ sum(lambda); % 计算累计贡献率 cumsum是求累加值的函数
disp('特征值为:')
disp(lambda') % 转置为行向量,方便展示
disp('贡献率为:')
disp(contribution_rate')
disp('累计贡献率为:')
disp(cum_contribution_rate')
disp('与特征值对应的特征向量矩阵为:')
% 注意:这里的特征向量要和特征值一一对应,之前特征值相当于颠倒过来了,因此特征向量的各列需要颠倒过来
% rot90函数可以使一个矩阵逆时针旋转90度,然后再转置,就可以实现将矩阵的列颠倒的效果
V=rot90(V)';
disp(V)
%% 计算我们所需要的主成分的值
m =input('请输入需要保存的主成分的个数: ');
F = zeros(n,m); %初始化保存主成分的矩阵(每一列是一个主成分)
for i = 1:m
ai = V(:,i)'; % 将第i个特征向量取出,并转置为行向量
Ai = repmat(ai,n,1); % 将这个行向量重复n次,构成一个n*p的矩阵
F(:, i) = sum(Ai .* X, 2); % 注意,对标准化的数据求了权重后要计算每一行的和
end