determining size of array that is formed via calculation - matlab

I am creating a 1 dimensional row array via a calculation
Lt_p= totalLn_p - ln_p
Which returns
Lt_p =
4.4408 4.3482 3.9962 3.4517 2.9009 2.3447 2.0648 1.7837 1.5015 1.0676 0.8665 0.6739 0.4822 0.2818 0.0820 0
Due to the nature of the calculation the last element will always be 0, I then need to use Lt_p in another calculation (by dividing it by another array).
However the other array will always have one less element than Lt_p, so obviously can not be divided.
The 0 element is not needed though so how do I resize Lt_p to not include the last element?

Are you sure that you will not need it? Otherwise a zero element is a good way determining the end of the data. Either you do as Divakar in the comment, otherwise you define an array ind = Lt_p(1:end-1). And always calls Lt_p(ind). The latter is of course a waste of resources and computation time if you is completely sure you will only need elements Lt_p(1:end-1).

Related

Write to the textbox only if the condition is true in Matlab

I struggle with printing text in my Matlab GUI.
I have code like this in my callback:
if Lia == ismember(handles.T(1:3),(1,1,1))
set(handles.t1, 'String', 'good day');
end
The problem is, I don't know how to check if in my array indexes from 1 to 3 I got this numbers: 1,1,1. I was looking to the documentation but it appears it says nothing about that (or I simply cannot find the proper answer).
You can simply use all and check to see if every element in the first three slots of your array match the values of 1 explicitly. I don't know the shape of your array so I'm going to force it to be a column vector. If the first three slots of the array was a row or column vector and if we assumed that the values of 1 are a column or row vector respectively then you're going to get a rather unpleasant surprise:
h = handles.T(1:3);
if all(h(:) == [1; 1; 1])
set(handles.t1, 'String', 'good day');
end
Note that I could have simply done all(h(:) == 1) as a special case since we are performing a comparison of every element in an array with a single value. However, I have a feeling that this may change for you, so I've decided to explicitly make a vector of 1s so you can change the contents of what you want to compare to at a later time.

MATLAB spending an incredible amount of time writing a relatively small matrix

I have a small MATLAB script (included below) for handling data read from a CSV file with two columns and hundreds of thousands of rows. Each entry is a natural number, with zeros only occurring in the second column. This code is taking a truly incredible amount of time (hours) to run what should be achievable in at most some seconds. The profiler identifies that approximately 100% of the run time is spent writing a matrix of zeros, whose size varies depending on input, but in all usage is smaller than 1000x1000.
The code is as follows
function [data] = DataHandler(D)
n = size(D,1);
s = max(D,1);
data = zeros(s,s);
for i = 1:n
data(D(i,1),D(i,2)+1) = data(D(i,1),D(i,2)+1) + 1;
end
It's the data = zeros(s,s); line that takes around 100% of the runtime. I can make the code run quickly by just changing out the s's in this line for 1000, which is a sufficient upper bound to ensure it won't run into errors for any of the data I'm looking at.
Obviously there're better ways to do this, but being that I just bashed the code together to quickly format some data I wasn't too concerned. As I said, I fixed it by just replacing s with 1000 for my purposes, but I'm perplexed as to why writing that matrix would bog MATLAB down for several hours. New code runs instantaneously.
I'd be very interested if anyone has seen this kind of behaviour before, or knows why this would be happening. Its a little disconcerting, and it would be good to be able to be confident that I can initialize matrices freely without killing MATLAB.
Your call to zeros is incorrect. Looking at your code, D looks like a D x 2 array. However, your call of s = max(D,1) would actually generate another D x 2 array. By consulting the documentation for max, this is what happens when you call max in the way you used:
C = max(A,B) returns an array the same size as A and B with the largest elements taken from A or B. Either the dimensions of A and B are the same, or one can be a scalar.
Therefore, because you used max(D,1), you are essentially comparing every value in D with the value of 1, so what you're actually getting is just a copy of D in the end. Using this as input into zeros has rather undefined behaviour. What will actually happen is that for each row of s, it will allocate a temporary zeros matrix of that size and toss the temporary result. Only the dimensions of the last row of s is what is recorded. Because you have a very large matrix D, this is probably why the profiler hangs here at 100% utilization. Therefore, each parameter to zeros must be scalar, yet your call to produce s would produce a matrix.
What I believe you intended should have been:
s = max(D(:));
This finds the overall maximum of the matrix D by unrolling D into a single vector and finding the overall maximum. If you do this, your code should run faster.
As a side note, this post may interest you:
Faster way to initialize arrays via empty matrix multiplication? (Matlab)
It was shown in this post that doing zeros(n,n) is in fact slow and there are several neat tricks to initializing an array of zeros. One way is to accomplish this by empty matrix multiplication:
data = zeros(n,0)*zeros(0,n);
One of my personal favourites is that if you assume that data was not declared / initialized, you can do:
data(n,n) = 0;
If I can also comment, that for loop is quite inefficient. What you are doing is calculating a 2D histogram / accumulation of data. You can replace that for loop with a more efficient accumarray call. This also avoids allocating an array of zeros and accumarray will do that under the hood for you.
As such, your code would basically become this:
function [data] = DataHandler(D)
data = accumarray([D(:,1) D(:,2)+1], 1);
accumarray in this case will take all pairs of row and column coordinates, stored in D(i,1) and D(i,2) + 1 for i = 1, 2, ..., size(D,1) and place all that match the same row and column coordinates into a separate 2D bin, we then add up all of the occurrences and the output at this 2D bin gives you the total tally of how many values at this 2D bin which corresponds to the row and column coordinate of interest mapped to this location.

Mean of outlinks of a sparse matrix

So I'm working with sparse matrix and I have to find out different info about a very big one (10^6 size) and I need to find out the mean of the outlinks. Just to be sure I think mean is what you get from 3+4+5/3=4, 4 is the mean.
I thought of something like this:
[row,col] = find(A(:,2),1,'first')
and then I would do 1/numberInThatIndex or something similar, since it's a S-matrix (pretty sure it's called that).
And I would iterate column by column but for some reason it's not giving me the first number in each column, if I do find(A(:,1),1,'first') it does give me the first in the first column, but not in the second if I change it to A(:,2).
I'd also need something to store that index to access the value, I thought of a 2xN vector but I guess it's not the best idea. I mean, find is going to give me index, but I need the value in that index, and then store that or show it. Not sure if I'm explaining myself properly but I'm trying, sorry about that.
Just to be clear both when I input A(:,1) and A(:,2) it gives me index from the first column, and I do not want that, I want first element found from each column, so I can calculate the mean out of the number in that index.
edit: allright it seems like that indeed does work, but when I was checking the results I was putting 3817 instead of 3871 that was the given answer and so I found a 0 when I wanted something that's not a zero. Not sure if I should delete all of this.
To solve your problem, you can do the following:
numberNonZerosPerColumn = sum(S~=0,1);
meanValue = nanmean(1./numberNonZerosPerColumn);
Count the number of nonzero elements in every column n(i)
Compute the values v(i) that are stored there, which are defined by v(i) := 1/n(i)
Take the mean of those values where n(i) is not zero (i.e. summing all those values, where v(i) is not NaN and divide by the number of columns that contain at least one zero)
If you want to treat columns without any nonzero entry as v(i):= 0, but still use them in your mean, you can use:
numberNonZerosPerColumn = sum(S~=0,1);
meanValue = nansum(1./numberNonZerosPerColumn)/size(S,2);

vector of variable length vectors in MATLAB

I want to sum up several vectors of different size in an array. Each time one of the vectors drops out of my program, I want to append it to my array. Like this:
array = [array, vector];
In the end I want to let this array be the output of a function. But it gives me wrong results. Is this possible with MATLAB?
Thanks and kind regards,
Damian
Okay, given that we're dealing with column vectors of different size, you can't put them all in a numerical array, since a numerical array has to be rectangular. If you really wanted to put them in the numerical array, then the column length of the array will need to be the length of the longest vector, and you'll have to pad out the shorter vectors with NaNs.
Given this, a better solution would be, as chaohuang hinted at in the comments, to use a cell array, and store one vector in each cell. The problem is that you don't know beforehand how many vectors there will be. The usual approach that I'm aware of for this problem is as follows (but if someone has a better idea, I'm keen to learn!):
UpperBound = SomeLargeNumber;
Array = cell(1, UpperBound);
Counter = 0;
while SomeCondition
Counter = Counter + 1;
if Counter > UpperBound
error('You did not choose a large enough upper bound!');
end
%#Create your vector here
Array{1, Counter} = YourVectorHere;
end
Array = Array(1, 1:Counter);
In other words, choose some upper bound beforehand that you are sure you won't go above in the loop, and then cut your cell array down to size once the loop is finished. Also, I've put in an error trap in case you're choice of upper bound turns out to be too small!
Oh, by the way, I just noted in your question the words "sum up several vectors". Was this a figure of speech or did you actually want to perform a sum operation somewhere?

Sort array in MATLAB

I have a one-column array that I would like to sort in descending order. The array has values ranging from 0 to approximately 10^14. When I sort the array with
sorted = sort(A,'descend')
and try to look at the ten largest values, I find that
sorted(1:10)
gives me
1.0e+14 *
5.1093
0.0000
0.0000
0.0000
etc... -- Displaying these first few, large entries tells me that there's only one non-zero element, which isn't true.
However, if I skip the first couple of entries, which are far greater than the rest of the array elements, I get
sorted(8:10) =
2.9754
2.4182
2.0799
Why does displaying these first few large array elements cause all others to be displayed as zero?
The first number in your list is a scale factor that multiplies the entire array that follows. Because of the difference in magnitude of the elements, you will need to play with the format settings. Try
format long
or
format long e
to see a better representation
You may find sprintf or num2str more useful for printing numbers at arbitrary precision.
See this related SO question.
Relevant Matlab docs:
http://www.mathworks.com/help/techdoc/ref/format.html
http://www.mathworks.com/help/techdoc/ref/num2str.html
http://www.mathworks.com/help/techdoc/ref/sprintf.html
They're displayed as zero because they are essentially zero when compared to the first element (that is, they're much much smaller than 10^14). But even if they're displayed as zero, they are NOT zero. Try typing in sorted(3): the result shouldn't be zero. (Edit: you already showed this above).
It's basically an issue of precision. Typing format long might also make this clearer.