过冷水诚挚邀请你加入Matlab仿真秀官方交流群进行Matlab学习、问题咨询、 Matlab相关资料下载,qq:927550334
经常使用matlab绘图或者做计算自然而然遇到一个很基础的步骤,数据处理,本期过冷水就和大家分享一下matlab数据预处理技巧。
过冷水最近在学习过程中遇到这么一个问题,需要生成一个向量,该向量具有以下特点:
1 元素都为整数;
2元素和为指定值;
3 元素分布不能具有倾向性,最大值和最小值不能受约束(可操控);
4 元素个数可固定。
过冷水基本上把不符合上述特性方法都摸索排除了一遍,我们先看一下网上攻略。
ansonzxy 方法十分简单,看上去似乎是正确的,过冷水多次尝试,向量元素不是随机整数,向量和不是固定值。
x=randn(1,4) 45 average=sum(sum(x))/4 x = 44.6258 45.6953 45.8776 46.0336 average = 45.5581
qingningleyun 方法确实可以生成一个指定向量元素个数,元素和为定值,元素值为整数,but!该矩阵具有明显的倾向性。
m = 1; % 根据每个元素的平均值,以正态分布产生随机值,方法较笨,参考参考 n = 45;s m = 54; R = []; S M = sum(R(:)) while S M ~= s m ss = s m; rc = m*n; R = []; for k=1:(m*n) pp = ss/rc; r = abs(round(pp*randn)); R = [R r]; ss = ss - r; rc = rc - 1; end S* = sum(R(:)); end R = reshape(R,m,n) R = 列 1 至 34 1 1 1 1 0 4 2 0 1 2 1 1 1 0 3 2 1 0 0 0 0 0 2 1 0 0 1 3 2 1 0 0 1 0 列 35 至 45 1 1 3 2 0 4 2 1 4 0 3 R = 列 1 至 34 1 0 1 1 3 0 0 0 2 2 1 1 0 1 1 1 0 2 0 1 1 1 0 1 1 1 2 0 1 3 3 1 1 0 列 35 至 45 4 1 4 1 2 2 0 1 2 3 0 R = 列 1 至 34 0 1 1 1 0 0 1 1 1 2 1 0 0 2 0 0 0 1 1 2 2 0 1 1 1 0 1 0 3 0 1 3 2 1 列 35 至 45 2 3 0 0 1 2 3 7 4 0 1 54
可以很明显的发现,前面数普遍偏小,后面数偏大,从其方法中就可以看出,其平均值方法就限定了元素值不能为54,等较大的值,所以该方法是有一点不合适的。
sum(cell2mat(arrayfun(@(x)randperm(45)==x,ones(54,1),'UniformOutput',false)),1) ans = 列 1 至 34 4 1 0 0 1 0 1 1 3 3 0 2 2 1 2 0 0 3 2 1 1 1 0 2 3 0 1 1 1 0 0 0 0 1 列 35 至 45 2 0 0 1 1 2 3 1 2 4 0 a = 列 1 至 34 1 0 0 1 4 2 0 1 0 0 3 1 1 2 2 3 0 2 2 0 1 1 0 0 1 1 0 2 3 0 0 1 0 1 列 35 至 45 3 0 2 2 2 3 1 1 1 3 0 a = 列 1 至 34 5 1 3 0 1 0 0 3 2 0 1 1 1 0 3 1 1 1 1 0 2 1 4 1 2 0 1 1 2 2 0 0 1 1 列 35 至 45 2 0 0 0 0 0 1 1 1 2 4 a = 列 1 至 34 1 0 0 3 1 0 0 1 2 1 0 2 3 1 1 1 1 2 1 2 0 2 1 1 2 1 0 0 1 2 1 0 4 3 列 35 至 45 2 1 0 3 0 0 0 3 1 1 2
maybe该方法是可以的,可是过冷水反复测试,发现生成元素值普遍偏小,我们并不能控制其元素取值范围。所以有一点小瑕疵。过冷水不知道如何在基于该方法的基础上控制元素值范围 。
该方法指定了向量元素范围,随机整数,固定和,完美!
clear S=54; Amin=0;%数据最小值 Amax=5;%数据最大值 SumA=S-1; n=0; while SumA<S n=n 1; temp=round(rand(1)*S); while temp>Amax temp=Amin round((Amax 1-Amin)*rand(1)); end STemp=SumA temp; if STemp<=S A(n)=temp; SumA=sum(A); else n=n-1; end end disp('A') disp(A) A 1 5 3 4 5 0 4 0 0 5 5 0 5 3 5 2 4 3 A 1 3 1 4 0 2 4 3 3 3 1 0 1 2 3 2 3 2 5 4 1 2 2 2 A 1 4 3 4 1 0 2 5 1 5 3 4 1 3 3 3 1 4 2 4
运行几次后,可以很明显的发现每次生成的向量元素个数都不固定。经过大量不完美案例演示,好了可以明显的发现,以上给出的方法并不是严格意义上的随机。总是有各种条件约束限制,过冷水就想如何综合各种方法,做出符合要求的向量,上面方法中可取的优点有round((Amax 1-Amin)*rand(1))
1 round((Amax 1-Amin)*rand(1))函数可以生成一个最大值和最小值之间的随机整数。
2 S=S-temp 的循环赋值方法可以保证向量和为固定值。
过冷水思路为生成一个1*n的空向量,每个元素代号为n1、n2、n3,第一个元素赋值n1=S,生成一个随机整数m1,S-m1为零, 赋值: n1=S,n2~nn=0;S-m为负,赋值:n1=S,n2~nn=0。S-m为正,可认为是剩余n-1项元素和,进行赋值n1=m1,n2=S-m1,进入循环赋值 再生成一个随机数m2,做n2-m2 的判断。
程序为:
clear S=54; Amin=0;%数据最小值 Amax=5;%数据最大值 SumA=S-1; n=0; A=zeros(1,45); A(1,1)=S; for i=1:44 temp=round(rand(1)*(Amax-Amin) 1) B=A(1,i)-temp if B>=0 A(1,i 1)=B A(1,i)=temp else B<0 A(1,i 1)=0 end end disp('A') disp(A) A 列 1 至 34 4 5 5 2 3 5 2 6 1 5 3 4 4 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 列 35 至 45 0 0 0 0 0 0 0 0 0 0 0 A 列 1 至 34 2 1 3 1 3 4 3 4 1 2 3 2 2 2 5 3 5 2 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 列 35 至 45 0 0 0 0 0 0 0 0 0 0 0 A 列 1 至 34 6 5 5 5 2 5 4 3 4 6 1 5 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 列 35 至 45 0 0 0 0 0 0 0 0 0 0 0
看上去过冷水编的程序没有问题,元素个数固定,元素和固定,but经过大致一看,该向量也是有明显的倾向性,基本后面的元素都是为0,就前面的元素数值,该问题通过程序就可以发现。过冷水在前人的程序中发现 randperm(n)函数可以剩下1~n的n个元素的乱序矩阵,就可以用该函数对A进行重排
rowrank = randperm(45); B = A(1,rowrank) rowrank = randperm(45); % 随机打乱的数字,从1~行数打乱 B = A(1,rowrank) B = 列 1 至 34 0 0 0 0 5 0 0 0 6 0 0 4 0 0 4 0 0 6 0 5 0 2 0 0 0 0 0 0 5 0 0 0 0 3 列 35 至 45 5 0 0 0 0 0 5 0 1 0 3
问题完美解决,我们也可以对temp=round(rand(1)*(Amax-Amin) 1)进行修改更好的控制元素值的分布。过冷水在刚接触到生成随机整数矩阵的时候,觉得这个问题So easy, 随着实际过程发现问题并没有想象中的简单,也是不断翻阅资料,才知道问题出在什么地方,如何特定问题,所以做的多了解才深入,才能学的多,关于随机数生成读者有其它类似的问题,可留言讨论,共同学习,共同进步。
过冷水发表于 仿真秀 平台原创文章,未经授权禁止私自转载,如需转载请需要和作者沟通表明授权声明,未授权文章皆视为侵权行为,必将追责。如果您希望加入Matlab仿真秀官方交流群进行Matlab学习、问题咨询、 Matlab相关资料下载均可加群:927550334。
精品回顾
过冷水和你分享 matlab读取存储各种文件的方法 文末有独家金曲分享