Concatenating numbers in matlab - matlab

I am trying to concatenate 0s and 1s in a matrix to form a binary number (as a string).
For example, [1 0 1;0 0 1] should output ['101';'001']
When trying this input however, I get ['1','1'] as a result. Why?
function result = generateBinary(ref_matrix)
[row col] = size(ref_matrix);
result = cell(1,row);
str = '';
for i=1:row
for j = 1:col
n = num2str(ref_matrix(i,j))
str = strcat(str, num2str(ref_matrix(i,j)));
str
result{1,i} = str;
str = '';
end
end
end

The first end is at the wrong place.
function result = generateBinary(ref_matrix)
[row col] = size(ref_matrix);
result = cell(1,row);
str = '';
for i=1:row
for j = 1:col
n = num2str(ref_matrix(i,j))
str = strcat(str, num2str(ref_matrix(i,j)));
str
end
result{1,i} = str;
str = '';
end
As the indent suggests, result{1,i} = str;str = ''; may not be part of the inner loop.

Related

Calculate a confusion matrix given two matrix matlab

I have two Xval(Predicted values) and Sv(validation test) matrices, one with the classifier output data and the other with the validation data for the same samples. Each column represents the predicted value, eg [0 0 1 0 0 0 0 0 0 0] represents digit 3 (1 in the digit that is). I would like to know if it is possible to calculate the confusion matrix in a vectorized way or with a built in function, the sizes of both matrices are 12000x10. The code who generates both matrices are this
load data;
load test;
[N, m] = size(X);
X = [ones(N, 1) X];
[Nt, mt] = size(Xt);
Xt = [ones(Nt, 1) Xt];
new_order = randperm(N);
X = X(new_order,: );
S = S(new_order,: );
part = 0.8;
Xtr = X(1: (part * N),: );
Xv = X((part * N + 1): N,: );
Str = S(1: (part * N),: );
Sv = S((part * N + 1): N,: );
v_c = [];
v_tx_acerto = [];
tx_acerto_max = 0;
c = 250;
w = (X'*X+c*eye(m+1))\X' * S;
Xval = Xv*w;
for i=1:12000
aux = Xval(i,:);
aux(aux == max(aux)) = 1;
aux(aux<1) = 0;
Xval(i,:) = aux;
end
There are build-in functions confusionmat or plotconfusion. But if you want to have full control, you can just write a simple function yourself, e.g:
function [CMat_rel,CMat_abs] = ConfusionMatrix(Cprd,Cact)
Cprd_uq = unique(Cprd);
Cact_uq = unique(Cact);
NumPrd = length(Cprd_uq);
NumAct = length(Cact_uq);
% assert(NumPrd == NumAct)
% allocate memory
CMat_abs = NaN(NumPrd,NumAct);
CMat_rel = NaN(NumPrd,NumAct);
for j = 1:NumAct
lgAct = Cact == Cact_uq(j);
SumAct = sum(lgAct);
for i = 1:NumAct
lgPrd = Cprd == Cact_uq(i);
Num = sum( lgPrd(lgAct) == true );
CMat_abs(i,j) = Num;
CMat_rel(i,j) = Num/SumAct;
end
end
end

How can i write a MATLAB function named dedbi that takes input xtx as string and returns another string xtxx as output.

dedbi reverse the words that is, ‘a’ will be replaced by ‘z’, ‘b’ will be replaced by ‘y’, ‘c’ will be replaced by ‘x’ and so on. dedbi will do the same for capital letter that is, it will replace the string ‘A’ with ‘Z’, ‘B’ with ‘Y’, ‘C’ with ‘X’, and so on. If I give function this string ‘ab AB’ function should return ‘zy ZY’, input other than English words it will return input as output that is input as ‘///\?’ would return output as ‘///\?’.
So far i write this code. I must admit this problem is from an assignment that I need to pass.
Thank You guys for your kind look.
function xtxx = dedbi(xtx)
txtt = char(xtx);
indexa = strfind(txtt,'a');
txtt(indexa) = 'z';
indA = strfind(txtt,'A');
txtt(indA) = 'Z';
indb = strfind(txtt,'b');
txtt(indb) = 'y';
indB = strfind(txtt,'B');
txtt(indB) = 'Y';
indc = strfind(txtt,'c');
txtt(indc) = 'x';
indC = strfind(txtt,'C');
txtt(indC) = 'X';
indd = strfind(txtt,'d');
txtt(indd) = 'w';
indD = strfind(txtt,'D');
txtt(indD) = 'W';
inde = strfind(txtt,'e');
txtt(inde) = 'v';
indE = strfind(txtt,'E');
txtt(indE) = 'V';
indf = strfind(txtt,'f');
txtt(indf) = 'u';
indF = strfind(txtt,'F');
txtt(indF) = 'U';
indg = strfind(txtt,'g');
txtt(indg) = 't';
indG = strfind(txtt,'G');
txtt(indG) = 'T';
indh = strfind(txtt,'h');
txtt(indh) = 's';
indH = strfind(txtt,'H');
txtt(indH) = 'S';
indi = strfind(txtt,'i');
txtt(indi) = 'r';
indI = strfind(txtt,'I');
txtt(indI) = 'R';
indj = strfind(txtt,'j');
txtt(indj) = 'q';
indJ = strfind(txtt,'J');
txtt(indJ) = 'Q';
indk = strfind(txtt,'k');
txtt(indk) = 'p';
indK = strfind(txtt,'K');
txtt(indK) = 'P';
indl = strfind(txtt,'l');
txtt(indl) = 'o';
indL = strfind(txtt,'L');
txtt(indL) = 'O';
indm = strfind(txtt,'m');
txtt(indm) = 'n';
indM = strfind(txtt,'M');
txtt(indM) = 'N';
indn = strfind(txtt,'n');
txtt(indn) = 'm';
indN = strfind(txtt,'N');
txtt(indN) = 'M';
indo = strfind(txtt,'o');
txtt(indo) = 'l';
indO = strfind(txtt,'O');
txtt(indO) = 'L';
indp = strfind(txtt,'p');
txtt(indp) = 'k';
indP = strfind(txtt,'P');
txtt(indP) = 'K';
indq = strfind(txtt,'q');
txtt(indq) = 'j';
indQ = strfind(txtt,'Q');
txtt(indQ) = 'J';
indr = strfind(txtt,'r');
txtt(indr) = 'i';
indR = strfind(txtt,'R');
txtt(indR) = 'I';
inds = strfind(txtt,'s');
txtt(inds) = 'h';
indS = strfind(txtt,'S');
txtt(indS) = 'H';
indt = strfind(txtt,'t');
txtt(indt) = 'g';
indT = strfind(txtt,'T');
txtt(indT) = 'G';
indu = strfind(txtt,'u');
txtt(indu) = 'f';
indU = strfind(txtt,'U');
txtt(indU) = 'F';
indv = strfind(txtt,'v');
indv(txtt) = 'e';
indV = strfind(txtt,'V');
txtt(indV) = 'E';
indw = strfind(txtt,'w');
txtt(indw) = 'd';
indW = strfind(txtt,'W');
txtt(indW) = 'D';
indx = strfind(txtt,'x');
txtt(indx) = 'c';
indX = strfind(txtt,'X');
txtt(indX) = 'C';
indy = strfind(txtt,'y');
txtt(indy) = 'b';
indY = strfind(txtt,'Y');
txtt(indY) = 'B';
indz = strfind(txtt,'z');
txtt(indz) = 'a';
indZ = strfind(txtt,'Z');
txtt(indZ) = 'A';
str = xtxx;
end
One approach -
%// in_str: Input string
%// Logical masks for upper and lower case letters
upper_mask = in_str>=65 & in_str<=90 %// OR isstrprop(in_str,'upper')
lower_mask = in_str>=97 & in_str<=122 %// OR isstrprop(in_str,'lower')
%// Initialize output string
out_str = in_str
%// Replace upper letters with "flipped" upper letters; repeat for small letters
out_str(upper_mask) = char(in_str(upper_mask) + 2*(78-in_str(upper_mask))-1)
out_str(lower_mask) = char(in_str(lower_mask) + 2*(110-in_str(lower_mask))-1)
Those numbers: 78 and 110 act as the "middle numbers" for the capital and small letters ranges respectively and are used for finding differences for each letter in those two categories.
Sample run -
>> in_str,out_str
in_str =
adzC+*6AY&‘///\?abAB
out_str =
zwaX+*6ZB&‘///\?zyZY
I just posted the solution, than I realised that I probably shouldn't solve your assignment. Anyways, here are a couple of tips for you:
You can use the function fliplr() to invert the elements in a (row) vector. (hint: reverse the alphabet)
If you do: [~, index] = ismember('abcd','ac'), than index will be: index=[1 3] (hint: the index of 'a' and c in the alphabet are the same as for z and 'y' in the reverse alphabet)
Pseudo code:
function out = func_name(in)
in = array of ascii values from original in values (can be done with one command)
out = vector if zeros the size of in (one command)
loop through all numbers of in
ch = current char ascii value (just because it is easier to write ch than in(index) in my opinion)
if ch is btw 65 and 96
subtract 65 so ch is 1-26
find 26-ch (invert)
add 65 so ch is 65-96
if ch is btw 97 and 122
do the same as above with adjusted numbers
end if
out(index_of_for_loop) = ch
end loop
end function
Note: In general, it is best to avoid code that has many copy-paste section because it can be difficult to edit quickly.
Here's a way to do that:
alphabet = 'abcdefghijklmopqrstuvwxyz';
ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
ralphabet = fliplr(alphabet);
RALPHABET = fliplr(ALPHABET);
txt = 'abc d ?!.< n AC';
[~, index] = ismember(txt,alphabet);
target = index ~= 0;
src = index(target);
[~, INDEX] = ismember(txt,ALPHABET);
TARGET = INDEX ~= 0;
SRC = INDEX(TARGET);
txtInvert = txt;
txtInvert(target) = ralphabet(src);
txtInvert(TARGET) = RALPHABET(SRC);
Output:
zyx w ?!.< n ZX
Another solution:
function xtx = dedbi(xtx)
xtx(xtx >= 'a' & xtx <= 'z') = 219 - xtx(xtx >= 'a' & xtx <= 'z');
xtx(xtx >= 'A' & xtx <= 'Z') = 155 - xtx(xtx >= 'A' & xtx <= 'Z');
end

Subscripted assignment dimension mismatch in matlab

I executed this code using Feature Matrix 517*11 and Label Matrix 517*1. But once the dimensions of matrices change the code cant be run. How can I fix this?
The error is:
Subscripted assignment dimension mismatch.
in this line :
edges(k,j) = quantlevels(a);
Here is my code:
function [features,weights] = MI(features,labels,Q)
if nargin <3
Q = 12;
end
edges = zeros(size(features,2),Q+1);
for k = 1:size(features,2)
minval = min(features(:,k));
maxval = max(features(:,k));
if minval==maxval
continue;
end
quantlevels = minval:(maxval-minval)/500:maxval;
N = histc(features(:,k),quantlevels);
totsamples = size(features,1);
N_cum = cumsum(N);
edges(k,1) = -Inf;
stepsize = totsamples/Q;
for j = 1:Q-1
a = find(N_cum > j.*stepsize,1);
edges(k,j) = quantlevels(a);
end
edges(k,j+2) = Inf;
end
S = zeros(size(features));
for k = 1:size(S,2)
S(:,k) = quantize(features(:,k),edges(k,:))+1;
end
I = zeros(size(features,2),1);
for k = 1:size(features,2)
I(k) = computeMI(S(:,k),labels,0);
end
[weights,features] = sort(I,'descend');
%% EOF
function [I,M,SP] = computeMI(seq1,seq2,lag)
if nargin <3
lag = 0;
end
if(length(seq1) ~= length(seq2))
error('Input sequences are of different length');
end
lambda1 = max(seq1);
symbol_count1 = zeros(lambda1,1);
for k = 1:lambda1
symbol_count1(k) = sum(seq1 == k);
end
symbol_prob1 = symbol_count1./sum(symbol_count1)+0.000001;
lambda2 = max(seq2);
symbol_count2 = zeros(lambda2,1);
for k = 1:lambda2
symbol_count2(k) = sum(seq2 == k);
end
symbol_prob2 = symbol_count2./sum(symbol_count2)+0.000001;
M = zeros(lambda1,lambda2);
if(lag > 0)
for k = 1:length(seq1)-lag
loc1 = seq1(k);
loc2 = seq2(k+lag);
M(loc1,loc2) = M(loc1,loc2)+1;
end
else
for k = abs(lag)+1:length(seq1)
loc1 = seq1(k);
loc2 = seq2(k+lag);
M(loc1,loc2) = M(loc1,loc2)+1;
end
end
SP = symbol_prob1*symbol_prob2';
M = M./sum(M(:))+0.000001;
I = sum(sum(M.*log2(M./SP)));
function y = quantize(x, q)
x = x(:);
nx = length(x);
nq = length(q);
y = sum(repmat(x,1,nq)>repmat(q,nx,1),2);
I've run the function several times without getting any error.
I've used as input for "seq1" and "seq2" arrays such as 1:10 and 11:20
Possible error might rise in the loops
for k = 1:lambda1
symbol_count1(k) = sum(seq1 == k);
end
if "seq1" and "seq2" are defined as matrices since sum will return an array while
symbol_count1(k)
is expected to be single value.
Another possible error might rise if seq1 and seq2 are not of type integer since they are used as indexes in
M(loc1,loc2) = M(loc1,loc2)+1;
Hope this helps.

Matlab Muliple delimiter removing during import

I am struggling with a problem and want a easy way around. I have a big array of data where I have some vector values as ( 1.02 1.23 3.32) format. I want it as 1.02 1.23 3.32 in a tabular form. The problem here is that there are two types of delimiter '(' and ')'.
can anyone help in writing a code for this? I have something like this:
filename = 'U.dat';
delimiterIn = '(';
headerlinesIn = 0;
A = textscan(filename,delimiterIn,headerlinesIn);
But one thing is that it only have one delimiter "(" and it does not work either.
Nishant
If your text file looks something like this:
(1 2 3) (4 5 6)
(7 8 9) (10 11 12)
You can read it in as strings and convert it to a cell array of vectors like this:
% read in file
clear all
filename = 'delim.txt';
fid = fopen(filename); %opens file for reading
tline = fgets(fid); %reads in a line
index = 1;
%reads in all lines until the end of the file is reached
while ischar(tline)
data{index} = tline;
tline = fgets(fid);
index = index + 1;
end
fclose(fid); %close file
% convert strings to a cell array of vectors
rowIndex = 1;
colIndex = 1;
outData = {};
innerStr = [];
for aCell = data % for each entry in data
sline = aCell{1,1};
for c = sline % for each charecter in the line
if strcmp(c, '(')
innerStr = [];
elseif strcmp(c, ')')
outData{rowIndex,colIndex} = num2str(innerStr);
colIndex = colIndex + 1;
else
innerStr = [innerStr, c];
end
end
rowIndex = rowIndex + 1;
colIndex = 1;
end
outData

incapsulation of a code inmatlab

my code is
pathname=uigetdir;
filename=uigetfile('*.txt','choose a file name.');
data=importdata(filename);
element= (data.data(:,10));
in_array=element; pattern= [1 3];
locations = cell(1, numel(pattern));
for p = 1:(numel(pattern))
locations{p} = find(in_array == pattern(p));
end
idx2 = [];
for p = 1:numel(locations{1})
start_value = locations{1}(p);
for q = 2:numel(locations)
found = true;
if (~any((start_value + q - 1) == locations{q}))
found = false;
break;
end
end
if (found)
idx2(end + 1) = locations{1}(p);
end
end
[m2,n2]=size(idx2)
res_name= {'one' 'two'};
res=[n n2];
In this code I finding a pattern in one of the column of my data file and counting how many times it's repeated.
I have like 200 files that I want to do the same with them but unfotunatlly I'm stuck.
this is what I have added so far
pathname=uigetdir;
files=dir('*.txt');
for k=1:length(files)
filename=files(k).name;
data(k)=importdata(files(k).name);
element{k}=data(1,k).data(:,20);
in_array=element;pattern= [1 3];
locations = cell(1, numel(pattern));
for p = 1:(numel(pattern))
locations{p} = find(in_array{k}== pattern(p));
end
idx2{k} = [];
how can I continue this code..??
OK, first define this function:
function [inds, indsy] = findPattern(M, pat, dim)
indices = [];
if nargin == 2
dim = 1;
if size(M,1) == 1
dim = 2; end
end
if dim == 1
if numel(pat) > size(M,1)
return; end
for ii = 1:size(M,2)
inds = findPatternCol(M(:,ii), pat);
indices = [indices; repmat(ii,numel(inds),1) inds]%#ok
end
elseif dim == 2
if numel(pat) > size(M,2)
return; end
for ii = 1:size(M,1)
inds = findPatternCol(M(ii,:).', pat);
indices = [indices; inds repmat(ii,numel(inds),1)]%#ok
end
else
end
inds = indices;
if nargout > 1
inds = indices(:,1);
indsy = indices(:,2);
end
end
function indices = findPatternCol(col, pat)
inds = find(col == pat(1));
ii = 1;
prevInds = [];
while ~isempty(inds) && ii<numel(pat) && numel(prevInds)~=numel(inds)
prevInds = inds;
inds = inds(inds+ii<=numel(col) & col(inds+ii)==pat(ii+1));
ii = ii + 1;
end
indices = inds(:);
end
which is decent but probably not the most efficient. If performance becomes a problem, start here with optimizations.
Now loop through each file like so:
pathname = uigetdir;
files = dir('*.txt');
indices = cell(length(files), 1);
for k = 1:length(files)
filename = files(k).name;
data(k) = importdata(files(k).name);
array = data(1,k).data(:,20);
pattern = [1 3];
indices{k} = findPattern(array, pattern);
end
The number of occurrences of the pattern can be found like so:
counts = cellfun(#(x)size(x,1), indices);