範囲を指定して最頻値

例えばA=[1,1,1,1,5, 2,2,2,2,3, 4,4,1]といった13×1の変数があるとします。
これらを上から順に5行毎に分けその最頻値を取りたいです。今回の場合はB=[1, 2, 4]といった感じで、最後は割り切れないがそのまま出力したいと思っています。
mode関数がよいようなのですが、以下のようにプログラムして上手くいきません。ご教授いただけると幸いです。よろしくお願いいたします。
for i = 1:length(A):5
k=i+4;
l=mode(A(i:k,:),2);
end

 Accepted Answer

Hernia Baby
Hernia Baby on 7 Sep 2022

1 vote

まずは準備します。
A = [1;1;1;1;5;2;2;2;2;3;4;4;1];
sz_A = size(A)
sz_A = 1×2
13 1
ここがミソになります。
remで余りを算出し、それを割る数(ここでは5)から引くと足りない数が出ます。
その分だけNaNを埋め込みます。そしてreshapeで5行×n列の行列に変換します。
num = 5;
B = [A;nan(num - rem(sz_A(1),num),1)];
B_re = reshape(B,5,[])
B_re = 5×3
1 2 4 1 2 4 1 2 1 1 2 NaN 5 3 NaN
modeはNaNを無視するのでそのまま使えます。
MODEs = mode(B_re)
MODEs = 1×3
1 2 4

6 Comments

Ochi Kai
Ochi Kai on 7 Sep 2022
ご回答ありがとうございます。無事にできました。
少し別の質問となってしまうかもしれないのですが、質問投降後に自身のプログラムを少し変え、あと少しで上手くいきそうなので可能であればそちらの方の解答もいただきたいです。
最後if文に入った処理までは上手くいくのですが、ifを抜けた後でエラーが出てしまいます。ifの処理をした後にfor文ごと抜け出すにはどうすればよろしいでしょうか?breakを使うと上手くいかなくて困ってました。
%空の変数を用意する
Y=length(A)/5;
Y = fix(Y);
Y = Y+1;
X=zeros(Y,1);
m=1;
for i = 1:5:length(A)
if i<length(A)
X(m,1)=mode(A(i:length(A),:));
end
k=i+4;
X(m,1)=mode(A(i:k,:));
m=m+1;
end
Hernia Baby
Hernia Baby on 7 Sep 2022
Edited: Hernia Baby on 7 Sep 2022
自作いいですね!確認してみました。
条件文を通らない場合はif, elseif, elseを活用しましょう。
------
訂正:条件が間違っていたので変更しました。
clc,clear
A = [1;1;1;1;5;2;2;2;2;3;4;4;1];
% ---- ここは ceil(length(A)/5) で代用可能
Y = length(A)/5; % サイズの割り算
Y = fix(Y); % ゼロ方向への丸め
Y = Y + 1; % 丸め+1
% ----
X = zeros(Y, 1);
m = 1;
% ---- elseの追加
for ii = 1:5:length(A)
k = ii + 4; % 訂正箇所
if k > length(A) % 訂正箇所
X(m, 1) = mode(A(ii:length(A),:));
else
X(m, 1) = mode(A(ii:k,:));
end
m = m + 1;
end
X
X = 3×1
1 2 4
Ochi Kai
Ochi Kai on 7 Sep 2022
ご回答ありがとうございます。質問の例で出した13×1なら出来たのですが、自分がやりたいのは約5000×1くらいの変数を50ずつで分割したいのですが、それでやるとエラーは出ませんが、最頻値の値が異なる数値を出してしまいます。以下コードです。何が原因なのでしょうか?変数はざっくりいうと1から1500辺りまでが1,1500から3000辺りが2、3000から4500辺りが3,4500から5000辺りまでが4が中心で、その間にいくつかの数値が混ぜこまれている、みたいなイメージです。このプロプログラムでは最初は1が出てこず2から最頻値が出てきてしまいます。
ちなみにHernia Baby様が最初に回答していただいたプログラムでは上手くいきました。
Y=length(A)/50;
Y = fix(Y);
Y = Y+1;
X=zeros(Y,1);
m=1;
for ii = 1:50:length(A)
if ii<length(A)
X(m,1)=mode(A(ii:length(A),:));
else
k=ii+49;
X(m,1)=mode(A(ii:k,:));
end
m=m+1;
end
Ochi Kai
Ochi Kai on 7 Sep 2022
一応例としてsaihin.csvファイルを添付させていただきました。
すみません、一部間違えていました…
以下のコードになります
clear,clc;
A = readmatrix('saihin.csv');
Y = length(A)/50;
Y = fix(Y);
Y = Y + 1;
X = zeros(Y,1);
m = 1;
for ii = 1:50:length(A)
k = ii + 49;
if k > length(A)
X(m,1)=mode(A(ii:length(A),1));
else
X(m,1)=mode(A(ii:k,1));
end
m = m + 1;
end
X'
ans = 1×100
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Ochi Kai
Ochi Kai on 7 Sep 2022
解決いたしました!いくつかの質問にも答えていただいて本当にありがとうございます。

Sign in to comment.

More Answers (0)

Products

Release

R2022a

Tags

Asked:

on 7 Sep 2022

Commented:

on 7 Sep 2022

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!