MATLAB round values such that none are zero - matlab

I have an array of values and I am trying to round them all to integers, but I don't want any of them to become zeros.
Some of the values look like this:
0.00001
-0.03
-0.000001
0.789
1
I would like the result after the rounding to look like this:
1
-1
-1
1
1
I tried round(), ceil(), floor(), etc. but I'm not sure what to do in this case. Any advice?

While fix allows you to round all numbers towards zero, there is no built-in to do the opposite. You could use ceil on the absolute value of the array to round each entry up to the next highest integer and then multiply by the sign of your data to apply the correct sign to the result.
result = sign(data) .* ceil(abs(data))
% 1
% -1
% -1
% 1
% 1

Related

How to create an adjacency/joint probability matrix in matlab

From a binary matrix, I want to calculate a kind of adjacency/joint probability density matrix (not quite sure how to label it as so please feel free to rename).
For example, I start with this matrix:
A = [1 1 0 1 1
1 0 0 1 1
0 0 0 1 0]
I want to produce this output:
Output = [1 4/5 1/5
4/5 1 1/5
1/5 1/5 1]
Basically, for each row, I want to calculate the proportion of times where they agreed (1 and 1 or 0 and 0). A will always agree with itself and thus have it as 1 along the diagonal. No matter how many different js are added it will still result in a 3x3, but an extra i variable will result in a 4x4.
I like to think of the inputs along i in the A matrix as the person and Js as the question and so the final output is a 3x3 (number of persons) matrix.
I am having some trouble with this on matlab. If you could please help point me in the right direction that would be fabulous.
So, you can do this in two parts.
bothOnes = A*A';
gives you a matrix showing how many 1s each pair of rows share, and
bothZeros = (1-A)*(1-A)';
gives you a matrix showing how many 0s each pair of rows share.
If you just add them up, you get how many elements they share of either type:
bothSame = A*A' + (1-A)*(1-A)';
Then just divide by the row length to get the desired fractional representation:
output = (A*A' + (1-A)*(1-A)') / size(A, 2);
That should get you there.
Note that this only works if A contains only 1's and 0's, but it can be adapted for other cases.
Here are some alternatives, assuming A can only contain 0 and 1:
If you have the Statistics Toolbox:
result = 1-squareform(pdist(A, 'hamming'));
Manual approach with implicit expansion:
result = mean(permute(A, [1 3 2])==permute(A, [3 1 2]), 3);
Using bitwise operations. This is a more esoteric approach, and is only valid if A has at most 53 columns, due to floating-point limitations:
t = bin2dec(char(A+'0')); % convert each row from binary to decimal
u = bitxor(t, t.'); % bitwise xor
v = mean(dec2bin(u)-'0', 2); % compute desired values
result = 1 - reshape(v, size(A,1), []); % reshape to obtain result

sum matrix using logical matrix - index exceeds matrix dimensions

I have two matrices.
mcaps which is a double 1698 x 2
index_g which is a logical 1698 x 2
When using the line of code below I get the error message that Index exceeds matrix dimensions. I don't see how this is the case though?
tsp = nansum(mcaps(index_g==1, :));
Update
Sorry I should have mentioned that I need the sum of each column in the mcaps vector
** Example of data **
mcaps index_g
5 6 0 0
4 3 0 0
6 5 1 1
4 6 0 1
8 7 0 0
There are two problems here. I missed one. Original answer is below.
What I missed is that when you use the logical index in this way, you are picking out elements of the matrix that may have different numbers of elements in each column, so MATLAB can't return a well formed matrix back to nansum, and so returns a vector. To get around this, use the fact that 0 + anything = 0
% create a mask of values you don't want to sum. Note that since
% index_g is already logical, you don't have to test equal to 1.
mask = ~index_g & isnan(mcaps)
% create a temporary variable
mcaps_to_sum = mcaps;
% change all of the values that you don't want to sum to zero
mcaps_to_sum(mask) = 0;
% do the sum
sum(mcaps_to_sum,1);
This is basically all that the nansum function does internally, is to set all of the NaN values to zero and then call the sum function.
index_g == 1 returns a 1698 x 2 logical matrix, but then you add in an extra dimension with the colon. To sum the columns, use the optional dim input. You want:
tsp = nansum(mcaps(index_g == 1),1);

MATLAB: playing 16-bit audio

I have a matrix (n,16) filled with audio samples of 16 bits each.
So the matrix could look like:
[0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1; 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]
and so on. How can i actually play this as sound? sound() is using double floating points (from -1 to 1 values). If i could just convert it to those values, I guess it would work, but im not sure. Any suggestions?
#AnderBiguri pretty much nailed it. Take your array, convert it to signed double, normalize and play it.
As you have a n x 16 matrix, where each row is a sample and each column is a bit for that number, first we need to convert that matrix into double format. We can use bin2dec to help us to do that. However, bin2dec takes in a string. As such, we can convert our matrix into a string array like so. Let's assume that inSound contains your sound matrix that you specified before.
I will also assume that your bits are in Big-Endian format, so the most significant bit is the left most bit, following down to the right most bit.
According to your comments, the numbers are signed 1's compliment. This means that should the most significant bit be 1, we simply invert the entire number. As such, we can figure out which rows are negative by checking the entire first column to see if there is a 1 or 0. We find the rows with 1 and simply take 1 and subtract every single element in the array. As such:
checkSign = inSound(:,1) == 1;
inSound(checkSign,:) = 1 - inSound(checkSign,1);
Therefore, when we convert our number to decimal, we simply find those rows again that should be negative and simply negate them. Let's convert our numbers first.
inSoundString = char(inSound + '0');
char converts each number in a matrix or vector into its string representation, assuming that the input into char is an ASCII code. As such, when we add with 0, we are adding each number in inSound with the numerical ASCII code that is representative of what 0 is in ASCII. This is our baseline to start with. After that, inSound will add either 0 or 1 to this numerical code so that when we convert this whole matrix into a string, we will finally get the string representation of those numbers.
Now convert the binary strings into actual numbers:
outSoundDec = bin2dec(inSoundString);
This will take each row and convert it into its decimal equivalent. Now, if your bits are in Little-Endian, you can use swapbytes to flip the bits so that you can transform the bits to Big-Endian before proceeding. Now that we have converted our numbers, we need to negate those rows that were supposed to be negative.
As such:
outSoundDec(checkSign) = -outSoundDec(checkSign);
Now we need to normalize this so that the range is between -1 to 1. Given that you have specified that the range is between [-32768, 32767], we simply divide all of our numbers by 32768. Therefore:
outSound = outSoundDec / 32768;
The above code will now normalize your signal so that it goes from -1 to 1. You can use sound(outSound, Fs); to play your sound where Fs is the sampling frequency your signal was obtained at.
Good luck!

Matlab find Series of First Negative Number

With a matrix of numbers in Matlab, how would you find the first negative number after a series of positive numbers?
So far, the only answer I could come up with was to write a loop to check for the first negative number, then record it, then look for the first positive number, and truncate the array there, then start over. Is there a vectorized way to do this?
e.g., I have x = [ -1 -5 -2 3 4 8 -2 -3 1 9], and I want this function or script to give me an array of y = [1 7].
or
find(diff(sign([1 x]))<0)
that is to say: find the locations in x where the difference in sign between successive elements is negative, oh and pushing a 1 onto the front of x to take care of the case where the 1st element is already negative
This is a quite home made solution, check it out
x = [ -1 -5 -2 3 4 8 -2 -3 1 9]
neg_idx = find(x < 0) % // negative values
z = [0 diff(neg_idx)] % // increments among indices of successive values;
% // consecutive indices return a difference of 1 whereas
% // non consecutive return a value greater than 1.
% // because the first element must be distinguished
% // we put the zero in front
id = find(z ~= 1) % // Every time there is a jump, a non consecutive neg.
% // value appears
% // thus the solution is in
y = neg_idx(id)
ans =
1 7
If neg_idx is empty (i.e. no negative value is involved) you will get an Index exceeds matrix dimensions, although the condition is immediate to check.

check if a column is composed of ones

does it exist a function built-in in matlab that checks if a column is all composed of ones? If it doesn't exist, there are some ways to build a function that work to achieve that porpouse?
all(A==1) should return true if it's composed of only 1s. Note that if you have any floating point precision errors, you should use all( abs(A-1) < eps ).
You can compare all entries of a column to 1 and sum the result
if sum(A(:,1)~=1)==0
% all ones
else
% not all ones
end
If A is a column vector:
A=[1 1 1 1]';
You could check like this:
sum(A==1)==length(A)
ans =
1