Repeating a vector function and storing into matrix - arrays

I have a function which creates a row vector(N) up to a specified number of N columns. This vector is generated by have the next column add a random integer between 1 and 5 to the previous column and keeps on going until column N. However, I wish to generate the function vector(200) 500 times, where each row vector is randomly generated, and then store each of these vector into a matrix of size 500x200.
I am currently a beginner and I'm just testing Matlab out.
What I tried to do is:
for r=1:500
row(r) = vector(200)
mat(r, :) = row(r)
end
However this does not seem to work. Any help or suggestion will be appreciated.
Thanks!

Assuming the first column is also a random number between 1 and 5, you can do this
result = cumsum(randi(5, 500, 200), 2);
How it works: randi(5, 500, 200) generates 500x200 random integers between 1 and 5; and cumsum(..., 2) gives the cumulative sum along each row.

Related

Matrix - Vector value matching

In my current project, I need to find values inside of an matrix that match with individual vector values. This is an example of the process; the main program has me using lat and lon values. But I create a 20x20 matrix and then a 20x1 array of randomly placed values.
When i do the for loop, each iteration of the Leroy vector is subtracted from every value in matrix. The first min function should return the smallest value from each column and its correspoding index. The second min function should return the smallest overall value from the first min function. and which index had the smallest value.
My concern is that im not sure which integer inside the matrix returned the smallest value. Is there a way I can use the indexes or something to figure that out?
Matrix = magic(20);
Leroy = randi(20,20,1);
for i = 1:length(Leroy)
[Jenkins, J] = min(min(Leroy(i) - Matrix);
end
As Cris Luego pointed in his comment, your for loop is not required since
Leroy(i) - Matrix
translates to something like
5 - [1 2 3; 4 5 6; 7 8 9]
However, your problem to get the index of the minimum in -Matrix can be solved by using min(-Matrix(:)):
[minimum, minidx] = min(-Matrix(:));
However, you will get the linear index. If you need the index for row and column, use
[colidx,rowidx] = ind2sub(size(Matrix), minidx);
Matrix = magic(20);
Leroy = randi(20,20,1);
for i = 1:length(Leroy)
[Jenkins, J] = min((Leroy(i) - Matrix).^2);
end
Using this will help get a match between two values in two arrays or a match between array values and matrix values

Adding random numbers to each number in a column of a table

I want to add random numbers to each element within the column of a table. This is is what I've been doing, but my approach adds same random number to all elements in that specific column.
NewEdge(:,2) = NewEdge(:,2)+ randi(3);
How can I add a different random number to each element?
NewEdge(:,2) = NewEdge(:,2)+ randi(3,size(NewEdge(:,2)); % Looks pretty
NewEdge(:,2) = NewEdge(:,2)+ randi(3,size(NewEdge,1),1); % Probably faster
randi(3) is a single scalar. Random, but still one number. You want to add a vector of random numbers, so call randi(imax,sz1,sz2), where imax is your maximum allowable integer, 3 in your case, and sz1,sz2 the sizes of your desired matrix, in this case you want as many rows as contained in NewEdge, and only a single column.

how to create array of random normalize number?

i want to create a matrix that each row of the matrix have 7 real random number in [0,1] and the sum of number in each rows should be equal to 1.
this matrix have 100 rows and 7 columns. how can i do it?
at first ,i create an array with 1 row and 7 columns. then write the code as bellow. i try normal the number in the rows but sum of each row became more than 1.how can i fix it? thank for taking your time.
a = rand(1,7);
for i=1:7
a(i) = a(i)/sum(a);
end
sum(a)
For 100 by 7, you can use bsxfun:
a = rand(100,7);
a = bsxfun(#rdivide,a.',sum(a.')).';
Here the sum of each row = 1
The problem is that by using a for-loop, you're changing the sum of the vector every loop iteration. You should take advantage of MATLAB's ability to act on whole matrices at once:
a = rand(1,7);
a = a./sum(a);

Matlab- Create cell confusion matrix

I have the following cell matrix, which will be used as a confusion matrix:
confusion=cell(25,25);
Then, I have two other cell arrays, on which each line contains predicted labels (array output) and another cell matrix containing the real labels (array groundtruth).
whos output
Name Size Bytes Class Attributes
output 702250x1 80943902 cell
whos groundtruth
Name Size Bytes Class Attributes
groundtruth 702250x1 84270000 cell
Then, I created the following script to create the confusion matrix
function confusion=write_confusion_matrix(predict, groundtruth)
confusion=cell(25,25);
for i=1:size(predict,1)
confusion{groundtruth{i},predict{i}}=confusion{groundtruth{i}, predict{i}}+1;
end
end
But when I run it in matlab I have the following error:
Index exceeds matrix dimensions.
Error in write_confusion_matrix (line 4)
confusion{groundtruth{i},predict{i}}=confusion{groundtruth{i}, predict{i}}+1;
I was curious to print output's and groundtruth's values to see what was happening
output{1}
ans =
2
groundtruth{1}
ans =
1
So, nothing seems to be wrong with the values, so what is wrong here? is the confusion matrix's indexing right in the code?
The error occurs in a for loop. Checking the first iteration of the loop is not sufficient in this case. Index exceeds matrix dimensions means there exists an i in the range of 1:size(output,1) for which either groundtruth{i} or output{i} is greater than 25.
You can find out which one has at least one element bigger than the range:
% 0 means no, there is none above 25. 1 means yes, there exists at least one:
hasoutlier = any(cellfun(#(x) x > 25, groundtruth)) % similar for 'output'
Or you can count them:
outliercount = sum(cellfun(#(x) x > 25, groundtruth))
Maybe you also want to find these elements:
outlierindex = find(cellfun(#(x) x > 25, groundtruth))
By the way, I am wondering why are you working with cell arrays in this case? Why not numeric arrays?

How do I check to see if two (or more) elements of an array/vector are the same?

For one of my homework problems, we had to write a function that creates an array containing n random numbers between 1 and 365. (Done). Then, check if any of these n birthdays are identical. Is there a shorter way to do this than doing several loops or several logical expressions?
Thank you!
CODE SO FAR, NOT DONE YET!!
function = [prob] bdayprob(N,n)
N = input('Please enter the number of experiments performed: N = ');
n = input('Please enter the sample size: n = ');
count = 0;
for(i=1:n)
x(i) = randi(365);
if(x(i)== x)
count = count + 1
end
return
If I'm interpreting your question properly, you want to check to see if generating n integers or days results in n unique numbers. Given your current knowledge in MATLAB, it's as simple as doing:
n = 30; %// Define sample size
N = 10; %// Define number of trials
%// Define logical array where each location tells you whether
%// birthdays were repeated for a trial
check = false(1, N);
%// For each trial...
for idx = 1 : N
%// Generate sample size random numbers
days = randi(365, n, 1);
%// Check to see if the total number of unique birthdays
%// are equal to the sample size
check(idx) = numel(unique(days)) == n;
end
Woah! Let's go through the code slowly shall we? We first define the sample size and the number of trials. We then specify a logical array where each location tells you whether or not there were repeated birthdays generated for that trial. Now, we start with a loop where for each trial, we generate random numbers from 1 to 365 that is of n or sample size long. We then use unique and figure out all unique integers that were generated from this random generation. If all of the birthdays are unique, then the total number of unique birthdays generated should equal the sample size. If we don't, then we have repeats. For example, if we generated a sample of [1 1 1 2 2], the output of unique would be [1 2], and the total number of unique elements is 2. Since this doesn't equal 5 or the sample size, then we know that the birthdays generated weren't unique. However, if we had [1 3 4 6 7], unique would give the same output, and since the output length is the same as the sample size, we know that all of the days are unique.
So, we check to see if this number is equal to the sample size for each iteration. If it is, then we output true. If not, we output false. When I run this code on my end, this is what I get for check. I set the sample size to 30 and the number of trials to be 10.
check =
0 0 1 1 0 0 0 0 1 0
Take note that if you increase the sample size, there is a higher probability that you will get duplicates, because randi can be considered as sampling with replacement. Therefore, the larger the sample size, the higher the chance of getting duplicate values. I made the sample size small on purpose so that we can see that it's possible to get unique days. However, if you set it to something like 100, or 200, you will most likely get check to be all false as there will most likely be duplicates per trial.
Here are some more approaches that avoid loops. Let
n = 20; %// define sample size
x = randi(365,n,1); %// generate n values between 1 and 365
Any of the following code snippets returns true (or 1) if there are two identical values in x, and false (or 0) otherwise:
Sort and then check if any two consecutive elements are the same:
result = any(diff(sort(x))==0);
Do all pairwise comparisons manually; remove self-pairs and duplicate pairs; and check if any of the remaining comparisons is true:
result = nnz(tril(bsxfun(#eq, x, x.'),-1))>0;
Compute the distance between distinct values, considering each pair just once, and then check if any distance is 0:
result = any(pdist(x(:))==0);
Find the number of occurrences of the most common value (mode):
[~, occurs] = mode(x);
result = occurs>1;
I don't know if I'm supposed to solve the problem for you, but perhaps a few hints may lead you in the right direction (besides I'm not a matlab expert so it will be in general terms):
Maybe not, but you have to ask yourself what they expect of you. The solution you propose requires you to loop through the array in two nested loops which will mean n*(n-1)/2 times through the loop (ie quadratic time complexity).
There are a number of ways you can improve the time complexity of the problem. The most straightforward would be to have a 365 element table where you can keep track if a particular number has been seen yet - which would require only a single loop (ie linear time complexity), but perhaps that's not what they're looking for either. But maybe that solution is a little bit ad-hoc? What we're basically looking for is a fast lookup if a particular number has been seen before - there exists more memory efficient structures that allows look up in O(1) time and O(log n) time (if you know these you have an arsenal of tools to use).
Then of course you could use the pidgeonhole principle to provide the answer much faster in some special cases (remember that you only asked to determine whether two or more numbers are equal or not).

Resources