summing numerical data using for loop - loops

I have this data file, for Matlab:
A 12 E 24
B 34 F 67
C 23 G 88
D 56 H 33
I would like to use a for loop to find the sum of the numbers in the 2nd and 4th column. I would really appreciate the help. Thank you.
This is what I have so far
`fid = fopen('patwts.dat')
if fid == -1
disp ('File open not successful')
else
disp ('File open is successful')
mat = textscan(fid,'%c %f %c %f')
[r c] = size(mat)
for i = 1:r
for j = 1:c
sum(j)
end
end
fclose(fid)
end`

Related

How to store submatrix in array

I have a square matrix B and I want to extract its submatrix which has consecutive row numbers and column numbered 1 through k, with k every natural number no more than n (size of my matrix). It also needs to have non-zero main diagonal entries.
Furthermore, I want to store the submatrices in an array form, (the next step is to check if their determinants are positive, but I won't include that in this question. Here is the code I have built:
for i = 1:n
for j = 1:n-i+1
submat2{i,j} = B([j:j+i-1],[1:i]);
for k = 1:i
maindiag{i,j,k} = prod((submat2{i,j}(i,i) ~= 0));
end
matmaindiag = []
for l = 1:size(maindiag(i,j,:),3)
matmaindiag = [matmaindiag cell2mat(maindiag(i,j,l))]
if prod(matmaindiag ~= 0)
boundsub{end+1} = submat2{i,j};
end
end
end
end
Is there any better way to do this?
For example, if I have:
B =
6 7 8 9
11 12 13 14
0 17 18 19
0 0 23 24
then the submatrices I would like to extract are:
B([1],[1]), B([1],[2]), B([1,2],[1,2]), B([2,3],[1,2]), B([1,2,3],[1,2,3]), B([2,3,4],[1,2,3]), and B itself
since they:
consisted of entries from columns of B that numbered consecutively from 1 through k (the size of the submatrix itself) and
From the consecutively numbered rows of B
Don't have any zero-valued diagonal entries
Thanks for any help and thoughts :)
I have come up with this
n = size(B,1)
for i = 1:n
for j = 1:n-i+1
submat{i,j} = B([j:j+i-1],[1:i]);
end
end
bousub = []
for i = 1:n
for j = 1:n-i+1
dia = diag(submat{i,j});
if (prod(dia) ~= 0)
bousub{end+1} = submat{i,j};
end
end
end

Vectorize 2d convolution on matlab

I got this Code for computing two dimensional convolution for two given arrays.
[r,c] = size(x);
[m,n] = size(y);
h = rot90(y, 2);
center = floor((size(h)+1)/2);
Rep = zeros(r + m*2-2, c + n*2-2);
return
for x1 = m : m+r-1
for y1 = n : n+r-1
Rep(x1,y1) = x(x1-m+1, y1-n+1);
end
end
B = zeros(r+m-1,n+c-1);
for x1 = 1 : r+m-1
for y1 = 1 : n+c-1
for i = 1 : m
for j = 1 : n
B(x1, y1) = B(x1, y1) + (Rep(x1+i-1, y1+j-1) * h(i, j));
end
end
end
end
How can i vectorize it , so no for loops exist ?
Thanks in advance.
Here's what I came up with:
%// generate test matrices
x = randi(12, 4, 5)
y = [2 2 2;
2 0 2;
2 2 2]
[r,c] = size(x);
%[m,n] = size(y); %// didn't use this
h = rot90(y, 2);
center = floor((size(h)+1)/2);
Rep = zeros(size(x)+size(h)-1); %// create image of zeros big enough to pad x
Rep(center(1):center(1)+r-1, center(2):center(2)+c-1) = x; %// and copy x into the middle
%// all of this can be compressed onto one line, if desired
%// I'm just breaking it out into steps for clarity
CRep = im2col(Rep, size(h), 'sliding'); %// 'sliding' is the default, but just to be explicit
k = h(:); %// turn h into a column vector
BRow = bsxfun(#times, CRep, k); %// multiply k times each column of CRep
B = reshape(sum(BRow), r, c) %// take the sum of each column and reshape to match x
T = conv2(Rep, h, 'valid') %// take the convolution using conv2 to check
assert(isequal(B, T), 'Result did not match conv2.');
Here are the results of a sample run:
x =
11 12 11 2 8
5 9 2 3 2
7 9 3 4 8
7 10 8 5 4
y =
2 2 2
2 0 2
2 2 2
B =
52 76 56 52 14
96 120 106 80 50
80 102 100 70 36
52 68 62 54 34
T =
52 76 56 52 14
96 120 106 80 50
80 102 100 70 36
52 68 62 54 34

Replacing Matrix Values in MATLAB

I have a matrix such as
M = [ 1 3 2 4;
3 3 2 1;
2 4 1 3]
which has a base A = [ 1 2 3 4];
I also have another base B = [103 104 105 106];
I need to replace the values of A with values of B inside M. So my new M should be:
M1 = [ 103 105 104 106;
105 105 104 103;
104 106 103 105];
The elements are random numbers so I need to use indice one to one connection between A nd B.
Should I mention it? of course NO FOR LOOPS :D
Thanks
Here's a one-liner for you:
sum(bsxfun(#times, bsxfun(#eq, M, reshape(A,1,1,[])), reshape(B,1,1,[])), 3)
It's rather fast.
Benchmark
Here's the benchmarking code:
%// bsxfun party
tic
for k = 1:10000
M1 = sum(bsxfun(#times,bsxfun(#eq,M,reshape(A,1,1,[])),reshape(B,1,1,[])),3);
end
toc
%// Using ismember
tic
for k = 1:10000
[idx,b] = ismember(M,A);
M(idx) = B(b(idx));
end
toc
%// Using a simple loop
tic
for k = 1:10000
M1 = M;
for t = 1:length(A)
M1(M == A(t)) = B(t);
end
end
toc
The results are:
Elapsed time is 0.030135 seconds.
Elapsed time is 0.094354 seconds.
Elapsed time is 0.007410 seconds.
So this one-liner is faster than the elegant solution with ismember, but the simple (JIT-accelerated) loop beats both. Surprising, no? :)
If you are sure the new M contains only elements from the new base (same for the old M and the old base), you can use the second output of ismember:
>> [~,b] = ismember(M,A);
>> M = B(b)
M =
103 105 104 106
105 105 104 103
104 106 103 105
If your base is a simple function of your old base it can be trivial:
M1 = M + 102;
Otherwise this is a way:
M1 = M
for t = 1:length(A)
M1(M==A(t)) = B(t)
end
Based on the answer of #Rody an other solution:
[idx,b] = ismember(M,A);
M(idx) = B(b(idx))
The difference is that this will not break if A does not contain all elements of M. (Probably should not occur if it is a proper basis).

Octave read each line of file to vector

I have a file data.txt
1 22 34 -2
3 34 -3
2
3 43 -3 2 3
And I want to load this file onto Octave as separate matrices
matrix1 = [1; 22; 34 ;-2]
matrix2 = [3; 34 -3]
.
.
.
How do I do this? I've tried fopen and fgetl, but it seems as if each character is given its own spot in the matrix. I want to separate the values, not the characters (it's space delimited).
quick and dirty:
A = dlmread("file");
matrix = 1; # just for nice varname generation
for i = 1:size(A,1)
name = genvarname("matrix",who());
eval([name " = A(i,:);"]);
eval(["[_,__," name "] = find(" name ");"]);
end
clear _ __ A matrix i
The format needs to be as you specified.

problems with data acquisition from MATLAB

I previously asked for help in reading data from a text file generated by a C program (an Exe).
Using #second's solution, I solved the problem but yesterday I discovered that the output file is more complex than I had expected.
The file output is:
V|0|0|0|t|0|1|1|4|11|T4|H13||||||||||||
P|40|0.01|10|1|1|0|40|1|1|1||1|*||0|0|0
*|A1|A1|A7|A16|F|F|F|F|F|F|||||||||||||
*|codserv|area|codice|nome|tnom|tmin|tmax|pc|qc|susc|||||||
*|||||kV|kV|kV|MW|MVAR|S||||||||||||
N|I|1|N01|N01|132|125.4|138.6|0|0||||||||
N|I|1|N02|N02|20|19|21|0|0|||||||||||||
N|I|1|N03|N03|20|19|21|1.013532234|0.49087611||||||||
N|I|1|N04|N04|20|19|21|0.390791617|0.189269056||||||||
N|I|1|N05|N05|20|19|21|0.180634542|0.121387171||||||||
N|I|1|N06|N06|20|19|21|0.709472564|0.343613323||||||||
N|I|1|N07|N07|20|19|21|0.103495727|0.069549543||||||||
N|I|1|N08|N08|20|19|21|0.351712456|0.170342158||||||||
N|I|1|N09|N09|20|19|21|0.097697904|0.06565339||||||||
N|I|1|N10|N10|20|19|21|0.162165157|0.078540184||||||||
N|I|1|N11|N11|20|19|21|0|0||||||||
*|A1|A8|A7|A7|F|F|F|F||F||F
*|plev|area|codice|estr1|estr2|lung|imax|rsd|xsd|bsd1|bsd2|||
*|||||km|A|Ohm|Ohm||S||S
L|I|D10203|N02|N03|1.884|360|0.41071|0.207886957|3.19E-08|3.19E-08|||||||||||||
L|I|D10304|N03|N04|1.62|360|0.35316|0.1787563|3.19E-08|3.19E-08|||||||||||||
L|I|D10405|N04|N05|0.532|360|0.11598|0.058702686|3.19E-08|3.19E-08|||||||||||||
L|I|D10506|N05|N06|1.284|360|0.27991|0.14168092|3.19E-08|3.19E-08|||||||||||||
L|I|D10607|N06|N07|1.618|280|0.53879|0.194766124|3.00E-08|3.00E-08|||||||||||||
L|I|D10708|N07|N08|0.532|280|0.17716|0.064039294|3.00E-08|3.00E-08|||||||||||||
L|I|D10809|N08|N09|2|360|0.436|0.220686791|3.19E-08|3.19E-08|||||||||||||
L|I|D10910|N09|N10|2.4|360|0.5232|0.264824149|3.19E-08|3.19E-08||||||||||||
*|A1|A8|A7|A7|F|F|A1|F|F|F|F|F|F||F||F|||||||||||||||||||||||||
*|codserv|codice|estr1|estr2|vn1|vn2|nod1|varp|varm|np|Pb|rsd|xsd||bsd1||bsd2||||||||||||
*|||||kV|kV||%|%||MVA|%|%||%||%|||||
%%%%%------%%%%%------%%%% **(read up to here)**
other unnecessary data
The algorithm should:
skip the first 3 rows
skip fifth row
For the fourth row *|codserv|area|codice|nome|tnom|tmin|tmax|pc|qc|susc|||||||, save each string in a vector empty codeserv=[] area=[] codice=[] nome=[] tnom=[] tmin=[] tmax=[] pc=[] qc=[] susc=[]
Fill vectors with data and strings in the rows following the fourth
codeserv=[N N N N N N N N N N ....]
area=[I I I I I I I ....]
codice=[1 1 1 1 1 1 ...]
nome=[N01 N02 N03 N04 N05 ]
tnom=[N01 N02 N03 N04 N05]
tmin=[132 20 20.....]
tmax=[125.4 19 19 19 ....]
pc=[138.6 21 21 21....]
qc=[0 0 1.013532234 ....]
susc=[0 0 0.49087611]
Do the same with the data starting with the letter L. Read this line codice|estr1|estr2|lung|imax|rsd|xsd||bsd1||bsd2 and fill the vectors with values in the lines beginning with L
plev=[L L L L L L L ....]
area=[I I I I I I I ....]
codice=[D10203 D10304 ...]
estr1=[N02 N03 N04 N05 ...]
estr2=[N03 N04 N05...]
lung=[1.884 1,662 ....]
imax=[360 360 .....]
rsd=[number....]
xsd=[number....]
bsd1=[number ....]
bsd2=[number....]
I tried to adapt the code from the previous question, but given that the lines that start with N and L do not know how many I need to know how to read the first string and count the number N and L are.
read
[vp***NNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLL***]
length N
length L
skip 1 2 3 line
read 4 line, create vector
codeserv=[N N N N N N N N N N ....]
area=[I I I I I I I ....]
codice=[1 1 1 1 1 1 ...]
nome=[N01 N02 N03 N04 N05 ]
tnom=[N01 N02 N03 N04 N05]
tmin=[132 20 20.....]
tmax=[125.4 19 19 19 ....]
pc=[138.6 21 21 21....]
qc=[0 0 1.013532234 ....]
susc=[0 0 0.49087611]
skip length N +1 line
read *|plev|area|codice|estr1|estr2|lung|imax|rsd|xsd|bsd1|bsd2|||
skip length N +3 line
create
plev=[L L L L L L L ....]
area=[I I I I I I I ....]
codice=[D10203 D10304 ...]
estr1=[N02 N03 N04 N05 ...]
estr2=[N03 N04 N05...]
lung=[1.884 1,662 ....]
imax=[360 360 .....]
rsd=[number....]
xsd=[number....]
bsd1=[number ....]
bsd2=[number....]
close the cycle
I hope it is understandable. My biggest problem is counting the N and L in the text.
function readtest2()
fid = fopen('test2.txt');
skipLines(3)
names1 = getNames;
skipLines(1);
nEntries1 = countPrefix('N');
data1 = textscan(fid,'%s %s %d %s %s %d %d %f %f %f %[| ]', nEntries1, 'delimiter','|');
skipLines(2)
names2 = getNames;
skipLines(1);
nEntries2 = countPrefix('L');
data2 = textscan(fid,'%s %s %s %s %s %f %d %f %f %f %f %[| ]', nEntries2, 'delimiter','|');
fclose(fid);
getData(data1, names1);
getData(data2, names2);
function names = getNames()
names = fgetl(fid);
names = textscan(names,'%s','delimiter','|');
end
function getData(data, names)
for i = 1:size(data,2)-1
values = ( data{i}(1:end));
if(iscell(values))
values = cell2mat(values);
end
name = names{1}{i+1};
% very basic error checking
if(~strcmp(name, ''))
%save the value in the calling work space
assignin('base', name, values)
end
end
end
function skipLines(n)
while(n > 0)
fgetl(fid);
n = n - 1;
end
end
function n = countPrefix(prefix)
pos = ftell(fid);
n = 0;
currLine = fgetl(fid);
while(currLine(1) == prefix)
currLine = fgetl(fid);
n = n + 1;
end
fseek(fid, pos, 'bof');
end
end

Resources