calculate the x-axis average bar - matlab

I have a simple problem.
I have this code:
test = [30,40,60,30,20,10,5,5,3]
bar(test)
The bar represent the child number by family. For example, 30 family have 0 child and 10 family have 5 children.
I want to obtain the child average by family and of course I can't just use mean(test).

We can easily convert your data in a form where each entry of a vector represents an observation of a family with a value for the number of children. This way we generate a vector with length of the total number of families. Each entry is a number representing the amount of children of the observed family.
To do this we can use arrayfun and repmat to repeat the entries in cnt as many times as there are corresponding families in test. Since the output of arrayfun is a cell-array, we need to use cell2mat to convert it back to a 'normal' matrix. After that, obs is the above mentioned vector. Now we can simply use mean or var to calculate what you need.
Here is an example:
test = [30,40,60,30,20,10, 5 ,5, 3] % families
cnt = [ 0, 1, 2, 3, 4, 5, 6, 7, 8] % children per family in test
obs = arrayfun(#(s,c)repmat(c,1,s),test,cnt,'UniformOutput',false);
obs = cell2mat(obs);
mean(obs) % mean
var(obs) % variance
This is the result:
ans =
2.3103
ans =
3.2349
Note: I assume that there are 30 families with 0 children (as your text says) and not 30 families with one child (as your bar-plot says). Just adjust cnt to match your needs.
To get test and cnt back from obs, you can use hist like this:
[test,cnt] = hist(obs,unique(obs));
For the creation of your bar-plot, use bar with two arguments. This way you have the correct x-values (in this case cnt).
bar(cnt,test)
xlabel('Children per family')
ylabel('Number of Families')

Related

Frequency of maximum values occuring in columns

I have a 35 x 24 matrix of numbers. Each of the 35 rows obviously has a maximum value. I'm trying to write a short piece of code which determines which of the 24 columns contains the most of these max values. The catch is that no loops are allowed.
For example if the maximum values for 30 different rows all happened to lie in column 7 then I would want MATLAB to return the answer 7 since this is the column with the most max row values.
If the values in each row are unique, we can simply use the second output of max combined with the mode to figure out which column contains the maximum of each row most often.
% Find the column which contains the maximum value
[~, column] = max(data, [], 2);
result = mod(column);
However, below is a more general solution that allows a given maximum value to occur multiple times per row.
maximaPerColumn = sum(bsxfun(#eq, data, max(data, [], 2)), 1);
result = find(maximaPerColumn == max(maximaPerColumn));
Explanation
First we want compute the maximum value for each row (maximum across columns, dimension 2).
rowMaxima = max(data, [], 2);
Then we want to replace each row with a 1 if the value is equal to the max of that row and 0 otherwise. We can easily do this using bsxfun.
isMaxOfRow = bsxfun(#eq, data, rowMaxima);
Then we want to figure out how many times a given column contains a max of a row. We can simply sum down the columns to get this.
maximaPerColumn = sum(isMaxOfRow, 1);
Now we want to find the column which contained the maximum number of maxima. We use find due to the fact that more than one column could contain the same number of maxima.
result = find(maximaPerColumn == max(maximaPerColumn));
I think you are looking for this:
sum(A==max(A,[],2))
Example:
A = [1 1 1;
2 2 2;
3 2 1]
M = sum(A==max(A,[],2))
Returns:
[3 2 2]
The first column has the most row wise max values. You could use find to identify this column.
find(M==max(M))

How to plot numeric values in a column when values in another column are equal to specific number

How can I get the numeric values in a column (let's say column 10) when the numeric values in another column (let's say column 9) are equal to a specific number and plot this in a graph.
e.g., When values of column 9 == 4, get the corresponding value of column 10 and plot. I am using row index number as a marker for time.
I am plotting all of column 10 to get a waveform then I want to use the data of column 9 to add markers to my waveform that are representative of a command occurring at a certain point in time.
Here is my code:
E = csvread('Experiment_at_10_45_1.csv');
[signal_rows, signal_columns] = size(E);
t=(1:signal_rows)/128; %128 samples per second
%% SNR plot for down frequency
plot(t,E(:,13),'k')
I hope my explanation is clear, as I have attempted to use a minimum working example of my code for the first time.
You'll want to use logical indexing to do this. You want to first create an array of 0 (false) and 1 (true) values where column 9 is equal to the value you want.
bool = E(:,9) == 4;
Then you'll want to use this 0 and 1 array as the row index. This will grab only the rows where column 9 was equal to 4. This is referred to as logical indexing.
E(bool, 10)
Then you can plot this
plot(t(bool), E(bool, 10))
As pointed out though, it is possible that the values aren't exactly to 4 due to floating point representation. To get around this, you just want to check if they are "close enough" using a very small epsilon.
bool = abs(E(:,9) - 4) < 1e-12;

Windowed subtraction of vectors that are not same size and then finding the mean of results

Good day,
I have a question what I want to achieve without the loop if possible. As title says I need to do windowed subtraction of vectors that are not same size and then finding the mean of results.
As example, let say that we have vector a = [2 3 4 5 6] and vector b = [1 2].
Program will have to move window with smaller numbers of elements (in this example vector b) over bigger one (vector a) and make operations on that way so it starts in first two elements in vector a and make subtraction with vector b and then sum results and find mean.
In this example it will just make calculation of subtraction 2-1 = 1, 3-2 = 1, summing results 1+1=2 and divide them with 2 (because vector b is that size). Final result is 1.
Then we move window on second elements of vector a (value 3 and 4 there, or index 2 and 3) and repeat process to the last elements of vector a.
For final result we need to get vector c who consist of elements [1 2 3 4] for this example.
Is this possible to do without looping because I have data sets over 10k of size. Thanks in advance
I can solve it with only one loop, iterating through "b" (two loops in your example).
Declare vectors (as columns! This is needed for matlabs computations to work)
a = [2 3 4 5 6]';
b = [1 2]';
Declare matrix for computed results. Each column represents subtractions of elements in "a" with one of the elements in "b".
c = zeros(length(a)-length(b)+1,length(b));
for k = 1:length(b)
c(:,k) = a(k:length(a)-length(b)+k)-b(k);
end
Now just sum the elements in "c" row wise and divide by length of "b" to get the mean
result = sum(c,2)/length(b);
You can simplify this for your exact example, but this is a generic solution for any vetors "a" and "b", where "b" is the smaller vector.

Matlab: Array of random integers with no direct repetition

For my experiment I have 20 categories which contain 9 pictures each. I want to show these pictures in a pseudo-random sequence where the only constraint to randomness is that one image may not be followed directly by one of the same category.
So I need something similar to
r = randi([1 20],1,180);
just with an added constraint of two numbers not directly following each other. E.g.
14 8 15 15 7 16 6 4 1 8 is not legitimate, whereas
14 8 15 7 15 16 6 4 1 8 would be.
An alternative way I was thinking of was naming the categories A,B,C,...T, have them repeat 9 times and then shuffle the bunch. But there you run into the same problem I think?
I am an absolute Matlab beginner, so any guidance will be welcome.
The following uses modulo operations to make sure each value is different from the previous one:
m = 20; %// number of categories
n = 180; %// desired number of samples
x = [randi(m)-1 randi(m-1, [1 n-1])];
x = mod(cumsum(x), m) + 1;
How the code works
In the third line, the first entry of x is a random value between 0 and m-1. Each subsequent entry represents the change that, modulo m, will give the next value (this is done in the fourth line).
The key is to choose that change between 1 and m-1 (not between 0 and m-1), to assure consecutive values will be different. In other words, given a value, there are m-1 (not m) choices for the next value.
After the modulo operation, 1 is added to to transform the range of resulting values from 0,...,m-1 to 1,...,m.
Test
Take all (n-1) pairs of consecutive entries in the generated x vector and count occurrences of all (m^2) possible combinations of values:
count = accumarray([x(1:end-1); x(2:end)].', 1, [m m]);
imagesc(count)
axis square
colorbar
The following image has been obtained for m=20; n=1e6;. It is seen that all combinations are (more or less) equally likely, except for pairs with repeated values, which never occur.
You could look for the repetitions in an iterative manner and put new set of integers from the same group [1 20] only into those places where repetitions have occurred. We continue to do so until there are no repetitions left -
interval = [1 20]; %// interval from where the random integers are to be chosen
r = randi(interval,1,180); %// create the first batch of numbers
idx = diff(r)==0; %// logical array, where 1s denote repetitions for first batch
while nnz(idx)~=0
idx = diff(r)==0; %// logical array, where 1s denote repetitions for
%// subsequent batches
rN = randi(interval,1,nnz(idx)); %// new set of random integers to be placed
%// at the positions where repetitions have occured
r(find(idx)+1) = rN; %// place ramdom integers at their respective positions
end

How to iterate over a changing vector in Matlab, not consecutive number?

I am really a beginner level at matlab. Now I want to have a loop, such that it iterates over a vector (not consecutive numbers) which contains a decreasing number of elements through iteration.
For example, I have [1; 2 ;3; 4] (thinking of it as person 1, 2, 3, 4)
then I want to do something such that for example person 1 and 4 gets food, person 2 and 3 left with no food.
In the next round, I want person 2 and 3 (those unassigned)to go through the assignment process again but not 1 and 4.
So I create a vector [2;3] to keep track of those left without food.
However,the for i=1:length(vector) gives me a series of consecutive numbers, what I want is
for i in vector do something; end
How to implement this?
when I just put
i=vector,
Matlab says Index exceeds matrix dimensions
If you want to loop through an arbitrary vector, just use that vector directly in a for loop. For example:
vector = [3, 4, 7, 1, 1]
for i = vector
disp(i)
end
will output 3 4 7 1 1. This is the equivalent of "for i in vector do something."
for i=1:length(vector) is giving you an index into the vector - it will always be consecutive because it represents the first..last position of the vector.
It sounds like you want to get an identifier out of the vector. You can do this within your existing loop: id=vector[i]
Have you thought about using Matlab structs?
s = struct(field1,value1,...,fieldN,valueN)
You can have an array 'people' of structs (of type person) which you can loop through...
for i=1:length(people)
if people(i).HasBeenFeed = False
% feed this person...
end
end