Change axis in histogram Matlab - arrays

I have an array A defined as
A = [1 0 1 1 0 1 2 3 1 2 3 ];
I want to make histogram of this array. I have tried with
hist(A)
But the problem is it shows value 1 is 5 times, 2 is 2 times and so on. But I want like it as at position 1 value 1, at 2 value is 0 , at 3 value is 1 and so on.

hist counts the number of occurances of each value in the input* and uses those for the height of the bars. This is why the output is what you mention. What you want, however, is just bar because your input A already is a histogram.
bar(A);
%// Add some histogram labels
xlabel('Index')
ylabel('Frequency')
*This isn't technically correct since it depends on the bins, but for this specific input it is the case.

Related

How do I generate a 2D Array with values, each with neighbours of different, non-repeating values?

I have a square 2D Array, which I wish to fill with values between 1 to 4.
For this to be correct, the neighbours of any of the values inside the array would need to look like this, as an example:
x 2 x
3 1 1
x 4 x
The x values are irrelevant to the middle value 1. As we can see, the neighbours of middle value 1 do not appear more than once, aside from itself
An incorrect value's neighbours would look like this:
x 2 x
3 1 2
x 4 x
One of the neighbours of middle value 1 appear more than once (the value of 2 appears twice), and we don't want this.
I have made a LUA solution for this problem, but it is very slow, as all it does is add 2 rules to the generation and runs through all combinations until it finds a valid one.
The rules being:
Corner neighbours (in our case the xs) cannot have the same value as the middle value
The next value OVER the relevant neighbours cannot have the same value as the middle value.
Explanation for rule 2:
y y y y
y 1 y x
y y y y
The x in this instance cannot have the value of 1, this applies for every vertical and horizontal direction (up-down-left-right)
EDIT: I now know I can just repeat a tileable pattern, but this is not what I wanted, as I do not want a clear repetition to be observable
You can simply repeat a pattern to get the desired array.
Row 1: 1 2 3 4 1 2 3... repeated for the required number of columns
Row 2: 3 4 1 2 3 4 1... repeated similarly
Row 3: Same as row 2
Row 4: Same as row 1
Row 5: Start repeating pattern from row 1
...continued for the required number of rows.
Here's an example for a 6x6 grid:
1 2 3 4 1 2
3 4 1 2 3 4
3 4 1 2 3 4
1 2 3 4 1 2
1 2 3 4 1 2
3 4 1 2 3 4
This is guaranteed to follow both rules, since:
The diagonal for a value of x here will always be 5 - x, and x != (5 - x) for x in [1,2,3,4].
The next over value for 1 will always be 3 and vice versa (in any direction), and same for 2 and 4.
Edit: In your comment, you've mentioned that you needed the array to be more "varied". Any form of randomness would mean that we can't use any patterns. In that case, your current solution can not be improved, since you can't use any pattern for optimisation.
You can use a Block that if repeated any number of times in any direction does not Break the neigbour-constraint. One such Block (I'm sure there are others, but this is the most trivial I think) would be:
1 1 2 2
3 3 4 4
2 2 1 1
4 4 3 3
You can repeat this Block any number of times in any direction and every cell will always have unique neighbors.
For example, if you need a 6x8-array just repeat the Block once to the right and down, and then slice according to the size you want:
1 1 2 2 1 1
3 3 4 4 3 3
2 2 1 1 2 2
4 4 3 3 4 4
1 1 2 2 1 1
3 3 4 4 3 3
2 2 1 1 2 2
4 4 3 3 4 4
Fun Fact: On further inspection one might recognize, that Abhinav Mathur and I came up with a somewhat similar solution. If you rotate my Block and swap the 2 with the 3, the pattern is the same. But his formulation with repeating rows instead of the whole block is probably easier to implement in most cases.
I write this as a second answer as there is a new requirement: Don't use any repeating pattern!
TLDR
Just fill the array row for row, left to right. With following constraint:
You want to fill the value x, then you only have to consider the values in the colored cells.
If the green cell is filled, then there is only one possibility for x (the one value that is not in either the green or red cells)
If the green cell is empty (you are at the left border). Then there are two options (one of the values that is not in the red cells). But the value that you choose has to be one of the values in the blue cells too (this is always possible) or otherwise it will be impossible to fill the value y later! If the blue cells aren't filled (right border) you can just ignore this secondary constraint.
Explanation
You can separate this into two independent problems. Think of your array like a chessboard and solve the numbers in the light and dark fields separately as they don't care about each other (light and dark don't share any neighbors because their neighbors are always of the opposite color respectively).
So you split your chessboard in light and dark (just to better understand, you don't have to actually separate the arrays).
Then you solve them separately with some simple constraints. The value (green) is not allowed to be equal to one of the values two cells apart (red):
Just fill the values row by row from left to right. You can only actually choose a value at the left border as the rest will be constrained by the other three values above. At this left border you have to be careful. The chosen value in the green cell has to be the same as one of the values in the blue cells. Otherwise the next cell (red) will be impossible!
Just do this for the light and dark cells and then put them back together:
This should be relatively easy to implement and really fast, as it is not brute-forcing anything but directly constructing a valid solution. When saying choose a number or fill values I mean to just get the possible values and choose one at random.
You can try yourself in excel too, it's like a really boring sudoku as there is actually not much to choose, it is really constrained :).

How to delete rows from a matrix that contain more than 50% zeros MATLAB

I want to remove the rows in an array that contain more than 50% of null elements.
eg:
if the input is
1 0 0 0 5 0
2 3 5 4 3 1
3 0 0 4 3 0
2 0 9 8 2 1
0 0 4 0 1 0
I want to remove rows 1 and 5, but retain the rest. The output should look like:
2 3 5 4 3 1
3 0 0 4 3 0
2 0 9 8 2 1
I want to do this using matlab
Use logical indexing into the rows, based on the mean of the rows of A negated:
t = .5; % threshold
A(mean(A==0,2) > t, :) = [];
What this does:
Compare A with 0: turns zeros into true, and nonzeros into false.
Compute the mean of each row.
Compare that to the desired threshold.
Use the result as a logical index to delete unwanted rows.
Equivalently, you can keep the wanted rows instead of removing the unwanted ones. This may be faster depending on the proportion of rows:
A = A(mean(A~=0,2) >= 1-t, :);
You can also use the standardizeMissing function and rmmissing function together to achieve this:
>> [~,tf] = rmmissing(standardizeMissing(A,0),'MinNumMissing',floor(0.5*size(A,2))+1);
>> A(~tf,:)
The call to standardizeMissing replaces the 0 values with NaN (the standard missing indicator for double), then the rmmissing call identifies in the logical vector tf the rows that have more than 50% of their entries as 0 (i.e., those rows that have more than floor(0.5*size(A,2))+1 0-valued entries. Then you can just negate the tf output and use it as an indexer. You can adapt the minimum number missing easily to satisfy whatever percentage criteria you want.
Also note that tf is a logical vector here that is only the size of the number of rows of A.
As I mentioned on Luis' answer, one downside to his approach is that it requires an intermediate logical array of the same size as A to be created, which can potentially incur a significant memory/performance penalty when working with large arrays.
An explicit looped approach with nnz (overly verbose, for clarity):
[nrows, ncols] = size(A);
maximum_ratio_of_zeros = 0.5;
minimum_ratio_of_nonzeros = 1 - maximum_ratio_of_zeros;
todelete = false(nrows, 1);
for ii = 1:nrows
if nnz(A(ii,:))/ncols < minimum_ratio_of_nonzeros
todelete(ii) = true;
end
end
A(todelete,:) = [];
Which returns the desired answer.

graph representing the randomization of each column in a binary matrix

Imagine the following binary image exemplified by the matrix below. This is a simplified version of the images I'll be working with:
0 1 0 1
0 1 1 1
0 0 0 1
0 1 1 1
I want to construct a graph that will represent the randomness of each column. My thought is to develop a random index = the total transitions between each value in the column / by the total possible transitions. In the matrix above, each column could have a total possible of 3 transitions.
For the example above:
Column 1 would have a random index of 0% (0/3)
Column 2 would have a random index of 66.7% (2/3)
Column 3 = 100% (3/3)
Column 4 = 0% (0/3) even though they are 1's and not 0's. Doesn't matter, I just want the transitions.
Can I draw a boundary around all the 1 values and then have MATLAB sum all of the boundaries?
To calculate what you are suggesting you can just do:
sum( diff(A) ~= 0 )
The diff(A) will take the forward difference down the columns and the sum will count the number of non-zero changes. So if you do this you will get:
ans =
0 2 3 0
Let your image be defined as
im = [ 0 1 0 1
0 1 1 1
0 0 0 1
0 1 1 1 ];
The random index you want can be computed as
result = sum(diff(im)~=0) / (size(im,1)-1);
Explanation: diff computes the difference between consecutive elemtents down each column. The result is compared against zero (~=0), and all nonzero values within each row are added (with sum). Finally, the result is divided by the maximum number os transitions, which is the number of rows minus 1 (size(im,1)-1)
Equivalently, you could use xor between consecutive rows:
result = sum(xor(im(1:end-1,:), im(2:end,:))) / (size(im,1)-1)

Calling multiple values from data frame by row and column in R

I'm working in R and I'd like to call a selection of values from a data frame by their column and row indices. However doing this yields a matrix rather than an array. I shall demonstrate:
Given the data.frame:
a = data.frame( a = array(c(1,2,3,4,5,6,7,8,9), c(3,3)) )
(for those of you who don't want to plug it in, it looks like this)
a.1 a.2 a.3
1 1 4 7
2 2 5 8
3 3 6 9
And lets say I have two arrays pointing to the values I'd like to grab
grab_row = c(3,1,2)
grab_col = c(1,2,1)
Now I'd expect this to be the code I want...
a[ grab_row, grab_col ]
To get these results...
[1] 3 4 2
But that comes out as a 3x3 matrix, which makes enough sense in and of itself
a.1 a.2 a.1.1
3 3 6 3
1 1 4 1
2 2 5 2
Alright, I also see my answer is in the diagonal of the 3x3 matrix... but I'd really rather stick to an array as the output.
Any thoughts? Danka.
Passing the row and column indices in as a two-column matrix (here constructed using cbind()) will get you the elements you were expecting:
a[cbind(grab_row, grab_col)]
[1] 3 4 2
This form of indexing is documented in ?"[":
Matrices and array:
[...snip...]
A third form of indexing is via a numeric matrix with the one
column for each dimension: each row of the index matrix then
selects a single element of the array, and the result is a vector.
Try this:
> mapply(function(i,j)a[i,j], grab_row, grab_col)
[1] 3 4 2
Works for both dataframes and matrices.

Look at each row separately in a matrix (Matlab)

I have a matrix in Matlab(2012) with 3 columns and X number of rows, X is defined by the user, so varies each time. For this example though I will use a fixed 5x3 matrix.
So I would like to perform an iterative function on each row within the matrix, while the value in the third column is below a certain value. Then store the new values within the same matrix, so overwrite the original values.
The code below is a simplified version of the problem.
M=[-2 -5 -3 -2 -4]; %Vector containing random values
Vf_X=M+1; %Defining the first column of the matrix
Vf_Y=M+2; %Defining the secound column of the matrix
Vf_Z=M; %Defining the third column of the matrix
Vf=[Vf_X',Vf_Y',Vf_Z']; %Creating the matrix
while Vf(:,3)<0
Vf=Vf+1;
end
disp(Vf)
The result I get is
1 2 0
-2 -1 -3
0 1 -1
1 2 0
-1 0 -2
Ideally I would like to get this result instead
1 2 0
1 2 0
1 2 0
1 2 0
1 2 0
The while will not start if any value is above zero to begin with and stops as soon as one value goes above zero.
I hope this makes sense and I have supplied enough information
Thank you for your time and help.
Your current problem is that you stop iterating the very moment any of the values in the third row break the condition. Correct me if I'm wrong, but what I think you want is to continue doing iterations on the remaining rows, until the conditions are broken by all third columns.
You could do that like this:
inds = true(size(Vf,1),1);
while any(inds)
Vf(inds,:) = Vf(inds,:)+1;
inds = Vf(:,3) < 0;
end
Of course, for the simple addition you provide, there is a better and faster way:
inds = Vf(:,3)<0;
Vf(inds,:) = bsxfun(#minus, Vf(inds,:), Vf(inds,3));
But for general functions, the while above will do the trick.

Resources