How do I replace a single value within a .m matlab file? - file

I have a .m file that contains a struct with some matrices:
%mymatfile.m
function [mymatrix,anothermatrix] = mymatfile;
mymatrix = [
1 2 0.0010 0.0010 0.0000 2.0000 2.0000 2.0000 1 0 1
2 3 2.0014 0.0007 0.0000 0.5000 0.5000 0.5000 0 0 1
3 4 0.0301 0.0001 4.0000 0.5000 0.5000 0.5000 1.16 0 1
4 5 0.0791 0.0450 0.0000 0.5000 0.5000 0.5000 0 0 1
5 6 1.0482 0.0233 0.0000 0.5000 0.5000 0.5000 0 0 1
5 7 7.5130 0.0467 0.0000 0.5000 0.5000 0.5000 0* 0 1
7 8 9.0161 0.0008 0.0000 0.5000 0.5000 0.5000 0 0 1
7 9 0.9070 0.2310 0.0000 0.5000 0.5000 0.5000 0 0 1
];
anothermatrix = [
2 0 0 3 0 10 0
9 0 0 3 0 10 0
%];
How do I change just the starred value (mymatrix(3,9)) and save the file, whilst retaining its structure/formatting? I need to perform the update from another matlab script.

You could save the entries of mymatrix in a text file, say mymatrix_text.
Then you make your function read that text file, i.e.
%mymatfile.m
[mymatrix,anothermatrix] = function get_my_matrices()
fid = fopen(mymatrix_text);
mymatrix = fscanf(fid, '%g ');
fclose(fid);
% anothermatrix = %% you can do the same above..
end
Now if you need to modify your matrix, you should just modify the text file -which is way easier and doesn't involve changing your .m file.
(For instance you may create another function to read mymatrix_text and change the desired values).
This approach looks more robust to me.

Substitute a number in for the old one. The fields seem to be tab delimited.

Here's how I did it in the end (note that S is the value used to update the file):
fid = fopen('mymatfile.m') % open settings file
fseek(fid,1196,-1) % set read position
Line = fgets(fid) % read in line
Refline = Line % set reference for search and replace later
Line(47:51) = S % update specific characters in the line with new setting
fclose(fid) % close file
wholefile = fileread('test.m') % read in entire file
newfiledata = strrep(wholefile,Refline,Line) % replace line
fid2 = fopen('mymatfile.m','w') % open file to write
fprintf(fid2,'%s',newfiledata) % save to file
fclose(fid2)
With help from here: [http://www.mathworks.com/matlabcentral/answers/7066].

Related

interp1 does not return expected results

I'm trying to interpolate the values of a vector but I can't seem to understand how to use interp1.m properly.
This is what I'm expecting:
a=[1 0 2 0 3 0 4];
//Use of interp1.m
Output=[1 1.5 2 2.5 3 3.5 4];
a=[1 0 0 2 0 0 3 0 0 4];
//Use of interp1.m
Output=[1 1.32 1.65 2 2.31 2.64 3 3.3 3.63 4];
Assuming you always want to fill the zero values of your vector:
a = [3 0 6 0 5 0 4]
mask = logical(a);
nvec = 1:numel(a);
a(~mask) = interp1(nvec(mask),a(mask),nvec(~mask))
a =
3.0000 4.5000 6.0000 5.5000 5.0000 4.5000 4.0000
Assuming you want to stretch your vector by a certain factor:
a = [3 6 5 4]
stretchfactor = 2;
a = interp1((1:numel(a))*stretchfactor - 1, a, 1:numel(a)*stretchfactor - 1)
a =
3.0000 4.5000 6.0000 5.5000 5.0000 4.5000 4.0000
This is how I think you meant to use interp1:
a=[1 2 3 4];
N=7; % # of points to interpolate between a(1)=1 and a(end)=4
xi=linspace(a(1),a(end),N); % the new intep x-grid
ai=interp1(1:numel(a),a,xi)
As a side note, if you just want to have linear spacing between any two values, just use linspace, for example:
linspace(1,4,10)
ans =
1.0000 1.3333 1.6667 2.0000 2.3333 2.6667 3.0000 3.3333 3.6667 4.0000
the zeros are real values that you entered, if you interpolate on them you "force" the result to pass through them...

Replace some values of one MATLAB matrix with values from another

I'm a new programmer, working in MATLAB, and I am hoping to substitute some values in one of my matrices with information from another matrix.
So, for example, supposing I have one matrix [A]:
A = [0 0 0 0 0
.5 0 .2 .8 0
1 .3 1 .1 .1
1 1 .4 1 1
1 1 1 1 1]
And another matrix B:
B = [.4 .3 .2 .1 .2]
I would like to replace the first nonzero value in A with the one in the same column in matrix B such that:
A_new = [0 0 0 0 0
.4 0 .2 .1 0
1 .3 1 .1 .2
1 1 .4 1 1
1 1 1 1 1]
There are some values between 0 and 1 that I want to keep untouched which precludes just changing everything between 0 and 1 (exclusive). I'm sure the solution will involve an if statement and possibly a for loop, but I'm not sure how to set it up. Any advice is appreciated!
Try this:
[~, row] = max(A~=0);
A(row + (0:size(A,1):numel(A)-1)) = B
How it works:
The first line produces a vector row containing the index of the first nonzero row in each column. This use of max is a "column-wise find" of sorts. Namely, max works down each column and tells you the row index of the maximum value in that column. Since each column only contains 0 or 1, there may be several maximizing (1) values; max gives the (index of) the first one.
In the second line that vector is transformed into a linear index to replace those elements of A.
Another way, though probably inefficient, is to use find and search for row and column locations that are non-zero. Once you find this, because MATLAB searches for non-zero entries column-wise, you can apply diff to the column indices and find transitions. The elements on the right-hand of the transition denote the first non-zero value for each column. Once you find these locations, get the corresponding row locations for these entries, create a new matrix A_new that is a copy of A, then change the corresponding entries to B. You'll need to use sub2ind for the assignment.
Something like this:
%// Define matrix
A = [0 0 0 0 0
.5 0 .2 .8 0
1 .3 1 .1 .1
1 1 .4 1 1
1 1 1 1 1];
%// Find non-zero entries
[row,col] = find(A);
%// Figure out the column locations that are the first non-zero for each column
ind = diff([Inf; col]) ~= 0;
%// Create a new matrix that is a copy of the old one
A_new = A;
%// Create the B vector
B = [.4 .3 .2 .1 .2];
%// Do the assignment
A_new(sub2ind(size(A), row(ind), (1:size(A,2)).')) = B;
Doing sub2ind is perhaps inefficient because there is a lot error checking done and that can slow things down. You can compute the linear indices manually by:
columns = size(A,2);
A_new((0:columns-1).'*columns + row(ind)) = B;
Running the above code, we get:
>> A
A =
0 0 0 0 0
0.5000 0 0.2000 0.8000 0
1.0000 0.3000 1.0000 0.1000 0.1000
1.0000 1.0000 0.4000 1.0000 1.0000
1.0000 1.0000 1.0000 1.0000 1.0000
>> A_new
A_new =
0 0 0 0 0
0.4000 0 0.2000 0.1000 0
1.0000 0.3000 1.0000 0.1000 0.2000
1.0000 1.0000 0.4000 1.0000 1.0000
1.0000 1.0000 1.0000 1.0000 1.0000

Fast column by column array division

Suppose that M and N are two Arrays. In simplest case, M and N like this:
1 14 7 80
2 15 8 12
3 16 9 11
(3 Rows and 4 Columns)
I want to divide column 1 by All three Columns, then divide column 2 by All three Columns and then divide column 3 by All three Columns.
What is the fastest way to do it? ( Surely, using for-loop is not a good algorithm. )
EDIT:
here is my for-loop code:
idx = 1;
for i = 1 : size(N,2)
for j = 1 : size(M,2)
u(:,idx)=N(:,i) ./ M(:,j);
idx = idx + 1;
end
end
How about using bsxfun and permute
Assuming M and N are same and equal to A
out = bsxfun(#rdivide, permute(A,[1 3 2]), A)
Input:
A =
1 14 7 80
2 15 8 12
3 16 9 11
Results for your Sample Input:
out(:,:,1) =
1.0000 0.0714 0.1429 0.0125
1.0000 0.1333 0.2500 0.1667
1.0000 0.1875 0.3333 0.2727
out(:,:,2) =
14.0000 1.0000 2.0000 0.1750
7.5000 1.0000 1.8750 1.2500
5.3333 1.0000 1.7778 1.4545
out(:,:,3) =
7.0000 0.5000 1.0000 0.0875
4.0000 0.5333 1.0000 0.6667
3.0000 0.5625 1.0000 0.8182
out(:,:,4) =
80.0000 5.7143 11.4286 1.0000
6.0000 0.8000 1.5000 1.0000
3.6667 0.6875 1.2222 1.0000
If
A = [1 14 7 80
2 15 8 12
3 16 9 11]
Then
bsxfun(#ldivide, prod(A,2), A).*A
returning
ans =
0.0001 0.0250 0.0062 0.8163
0.0014 0.0781 0.0222 0.0500
0.0019 0.0539 0.0170 0.0255
So the idea is to just divide every element by ALL the other elements in that row (i.e. by the product of the row, prod(A,2)) and then just multiply back by the original number so cancel the fact that you've divided by it (i.e. the .*A at the end). So ans(2,3) above is 0.0222 which equals (8/(2*15*8*12))*8 where (2*15*8*12) is the product of row 3.
NOTE this answers the original question (i.e. the question you describe) and does NOT answer the question that your code implies

how to create an arrays from rows using Matlab

Hi guys i need your help, so i have an array
a b c n
1 1 2 4
1 3 2 6
1 6 0 7
and i want to create another array form each rows of my array, see picture below.
I tried using this code:
assuming that my data is located at array M so,
for x=1:10
d = M(:,4)/(M(:,1) + M(:,2) + M(:,3) + x)
end
but it doesn't give my desired output
in excel you just only write the equation and drag it down, in you will have the answer but i don't know how to do it in matlab, i think we could use for loop. thanks.
PLEASE SEE THE RED BOX THAT'S MY DESIRED OUTPUT
The equivalent in Matlab would be:
data = [...
1 1 2 4;
1 3 2 6;
1 6 0 7]
x = (1:10).';
f = #(t) data(t,4)./(data(t,1) + data(t,2) + data(t,3) + x )
y = [ x f(1) x f(2) x f(3) ]
or even simpler:
N = 10;
f = #(t) [(1:N).' data(t,4)./(data(t,1) + data(t,2) + data(t,3) + (1:N).' )]
y = [ f(1) f(2) f(3) ]
the number in f(...) always indicates which row, respectively which y e.g. y1, y2, etc. you are calculating for each column of the output. The brackets [...] are concatenating the result.
Be aware that you need to use the element-wise division operator ./
Generalized for an n x m sized input array, but assuming that the n-column is always the last one of your input Matrix:
N = 10;
f = #(t) [(1:N).' data(t,end)./(sum( data(t,(1:end-1))) + (1:N).' )]
y = cell2mat(arrayfun(f, 1:size(data,1),'uni',0))
But in this case you should think about, if a more vectorized approach like Divakar's answer might be more appropriate.
result:
y =
1 0.8 1 0.85714 1 0.875
2 0.66667 2 0.75 2 0.77778
3 0.57143 3 0.66667 3 0.7
4 0.5 4 0.6 4 0.63636
5 0.44444 5 0.54545 5 0.58333
6 0.4 6 0.5 6 0.53846
7 0.36364 7 0.46154 7 0.5
8 0.33333 8 0.42857 8 0.46667
9 0.30769 9 0.4 9 0.4375
10 0.28571 10 0.375 10 0.41176
Vectorized approach to get the desired output with another good case for bsxfun to have the desired output for a generic m x n sized input array -
N = 10; %// Number of rows in the output
[m,n] = size(M) %// Get size
sum_cols = sum(M(:,1:n-1),2) %// sum along dim-2 until the second last column
sum_firstN = bsxfun(#plus,sum_cols,1:N) %// For each column-sum, add 1:N
out1 = bsxfun(#ldivide,sum_firstN,M(:,n)).'%//'# elementwise divide by last col
out = [repmat([1:N]',1,n); out1] %//'# Concatenate with starting columns of 1:N
out = reshape(out,N,[]) %// Reshape into desired shape
Code run for given 3 x 4 sized input array -
out =
1.0000 0.8000 1.0000 0.8571 1.0000 0.8750
2.0000 0.6667 2.0000 0.7500 2.0000 0.7778
3.0000 0.5714 3.0000 0.6667 3.0000 0.7000
4.0000 0.5000 4.0000 0.6000 4.0000 0.6364
5.0000 0.4444 5.0000 0.5455 5.0000 0.5833
6.0000 0.4000 6.0000 0.5000 6.0000 0.5385
7.0000 0.3636 7.0000 0.4615 7.0000 0.5000
8.0000 0.3333 8.0000 0.4286 8.0000 0.4667
9.0000 0.3077 9.0000 0.4000 9.0000 0.4375
10.0000 0.2857 10.0000 0.3750 10.0000 0.4118

How to make value in excel sheet become element of matrix in matlab

i have xls file name databus.xls, like this
No. Bus Code Voltage Mag. Fasa Beban Generator Stat Mvar
MW Mvar MW Mvar Qmin Qmax +Qc/-Ql'
1 1 1.04 0 50 30.99 0 0 0 0 0
2 0 1 0 170 105.35 0 0 0 0 0
3 0 1 0 200 123.94 0 0 0 0 20
4 2 1.02 0 80 49.58 318 0 0 0 0
how to make the value become component of matrix a
like
a=[1 1 1.04 0 50 30.99 ...etc
2 0 1 0 170 105.35 ...etc
...etc ]
If this is a one time operation, copy-paste is the simplest approach. If not, I would suggest xlsread
Try:
filename = 'databus.xls';
sheet = 1;
xlRange = 'A3:J7';
a = xlsread(filename, sheet, xlRange)
If there's only one sheet, you can skip the second argument and just do:
filename = 'databus.xls';
a = xlsread(filename,'A3:J7')
If you do not know the range, simply follow the documentation given in the link above:
num = xlsread(filename) reads data from the first worksheet in the
Microsoft® Excel® spreadsheet file named filename and returns the
numeric data in array num.
So, to show an example:
num = xlsread('test.xlsx')
num =
1.0000 1.0000 1.0000 50.0000 30.0000
2.0000 1.0000 1.0000 112.0000 60.0000
3.0000 2.0000 4.0000 40.0000 20.0000
4.0000 2.0000 3.0000 30.0000 20.0000
5.0000 3.0000 2.0000 60.0000 42.5000
As this reads all numeric data, you might get some rows with mostly NANs, if only a few of the columns contain numbers. If that's the case, you can simply delete those lines.
You have to split your task in two:
Export your data from Excel.
Import your data into Matlab.
For task 2, there are several options (links to official documentation are provided):
csvread
dimread
fscanf
importdata
Etc.?
See also Ways to Import Text Files and How do you create a matrix from a text file in MATLAB?.
If you use method 1 for task 2, then you have to export as csv from Excel.
Copy your worksheet into a new one.
Remove data not going into your matrix (as per your question, the first two rows).
Save as CSV.
Voilà

Resources