numpy: random select K items from total M(M>K) items? - matlab

Is there some handy implementation of Matlab function randperm in numpy that random select K items from totally M(M>K) items, and return the selected indice?
In Matlab,
randperm(100,10)
ans =
82 90 13 89 61 10 27 51 97 88

Yes, with the numpy.random.choice function.
>>> numpy.random.choice(100, 10, replace=False)
array([89, 99, 27, 39, 80, 31, 6, 0, 40, 93])
Note that the resulting range is 0 to M-1. If you need 1 to M like MATLAB, add 1 to the result:
>>> numpy.random.choice(100, 10, replace=False) + 1
array([ 28, 23, 15, 90, 18, 65, 86, 100, 99, 1])

Related

Sort 2 arrays/vectors based off 1 vector

I have 2 arrays (vectors? in m vernacular?) and I want to sort them in unison. How can I achieve this in Matlab?
For example; I have found the peaks from a histogram and they are stored in 2 arrays; peakXVals, peakYVals. They will always be arranged in ascending x axis index. So they will always look like:
peakXVals = [0, 3, 20, 77, 240];
peakYVals = [10, 999, 30, 40, 20];
I wish to sort both arrays based of the values in peakYVals in descending order. Ie from largest peak to smallest peak. So the desired result is:
peakXVals = [3, 77, 20, 240, 0];
peakYVals = [999, 40, 30, 20, 10];
What function's can I use to achieve this in Matlab?
Use sort:
peakXVals = [0, 3, 20, 77, 240];
peakYVals = [10, 999, 30, 40, 20];
>> [B,I] = sort(peakYVals, 'descend')
B =
999 40 30 20 10
I =
2 4 3 5 1
Then:
>> peakXVals_sorted = peakXVals(I)
peakXVals_sorted =
3 77 20 240 0
>> peakYVals_sorted = B
peakYVals_sorted =
999 40 30 20 10
You can arrange the two vectors as columns of a matrix and sort the rows of that matrix as atoms, in lexicographical order. Then the results are the columns of the sorted matrix:
tmp = sortrows([peakYVals(:) peakXVals(:)], 'descend');
peakYVals = tmp(:,1).';
peakXVals = tmp(:,2).';

How does [hist] from SMLib work in Pure Data?

I put the following message into a [hist 0 100 10] object (in SMLib):
0 1 2 3 3 4 5 5 5 6 7 7 7 7 8 9 10 11 11 11 11 11 12 13 14 15 16 17 18 19 20 21 22 23 23 23 23 23 23 23 23 23 23 67 99 100 107
I then hit 'absolute' and the following is output.
6 19 18 0 0 0 0 1 0 3
I was expecting it to count the occurrences of the numbers into even bins of size 10 but only six numbers are in the first bin, and the 67 is in the wrong bin!
I counted up how it's evaluated it and got the following:
[0, 1, 2, 3, 3, 4] = 6
[5, 5, 5, 6, 7, 7, 7, 7, 8, 9, 10, 11, 11, 11, 11, 11, 12, 13, 14] = 19
[15, 16, 17, 18, 19, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23] = 18
[] = 0
[] = 0
[] = 0
[] = 0
[67] = 1
[] = 0
[99, 100, 107] = 3
But.. I was expecting the following result.
16 14 13 0 0 0 1 0 0 3
Fixed it!
I was using [hist 0 100 10] when I should have been using [hist 5 105 10]!

I have a matrix 12*4, and I need to subtract the 3rd column elements of rows that are different

I have a 12x4 matrix in MATLAB,
A =[-1, 3, 152, 41.5 ;
3, 9, 152, 38.7 ;
9, 16, 152, 38.7 ;
16, 23, 129, 53.5 ;
23, 29, 129, 53.5 ;
29, 30, 100, 100 ;
30, 30.5, 83, 83 ;
30.5, 31, 83, 83 ;
31, 35, 83, 83 ;
35, 41, 129, 53.5 ;
41, 48, 129, 53.5 ;
48, 55, 152, 38.7 ] ;
and I need to find the changes in the rows by subtracting the 3rd column element of the 2nd row from the previous row 3rd column element if they are different else go to the 3rd row if the same.
The answer should be in the form:
B = [16, 23;
29, 29;
30, 17;
35, 46;
48, 23]
For example, the 3rd and the 4th row 3rd column elements are different, so if subtracted i got 23. Output B 1st column element will consist of the 4th row first column element.
%Given matrix
A =[-1, 3, 152, 41.5 ;
3, 9, 152, 38.7 ;
9, 16, 152, 38.7 ;
16, 23, 129, 53.5 ;
23, 29, 129, 53.5 ;
29, 30, 100, 100 ;
30, 30.5, 83, 83 ;
30.5, 31, 83, 83 ;
31, 35, 83, 83 ;
35, 41, 129, 53.5 ;
41, 48, 129, 53.5 ;
48, 55, 152, 38.7 ] ;
B=A(:,2:3); %Taking out the columns of our interest
B = B([diff(B(:,2))~=0; true],:); %Storing only those rows whose consecutive elements in the third column of A are different
B=[B(1:end-1,1) abs(diff(B(:,2)))] % First column is according to your condition and second column is the difference

how to plot column vector data along y-axis in matlab?

I have this row/column vector.
grades = [90, 100, 80, 70, 75, 88, 98, 78, 86, 95, 100, 92, 29, 50];
plot(grades);
In MATLAB, I want to plot grade values along x-axis and indices (1-14) along y-axis. By deafult, indices are plotted along x-axis. How it can be achieved?
grades = [90, 100, 80, 70, 75, 88, 98, 78, 86, 95, 100, 92, 29, 50];
figure;
plot(1:length(grades),grades); % Indices along X
figure;
plot(grades,1:length(grades)); % Indices along Y
If you want to plot data in Matlab. You have to define data sets for all the axis which you are interested in.
In your case, define x-axis data and y-axis data.
So for example your Y axis data would be
grades = [90 100 80 70 75 88 98 78 86 95 100 92 29 50];
for your x data you can use the following.
X = 1:14;
then you have the following plot command
plot(x,grades)

Select numbers from array which are much greater than the rest

Say there is an array of n elements, and out of n elements there be some numbers which are much bigger than the rest.
So, I might have:
16, 1, 1, 0, 5, 0, 32, 6, 54, 1, 2, 5, 3
In this case, I'd be interested in 32, 16 and 54.
Or, I might have:
32, 105, 26, 5, 1, 82, 906, 58, 22, 88, 967, 1024, 1055
In this case, I'd be interested in 1024, 906, 967 and 1055.
I'm trying to write a function to extract the numbers of interest. The problem is that I can't define a threshold to determine what's "much greater", and I can't just tell it to get the x biggest numbers because both of these will vary depending on what the function is called against.
I'm a little stuck. Does anyone have any ideas how to attack this?
Just taking all the numbers larger than the mean doesn't cut it all the time. For example if you only have one number which is much larger, but much more numbers wich are close to each other. The one large number won't shift the mean very much, which results in taking too many numbers:
data = [ones(1,10) 2*ones(1,10) 10];
data(data>mean(data))
ans =
2 2 2 2 2 2 2 2 2 2 10
If you look at the differences between numbers, this problem is solved:
>> data = [16, 1, 1, 0, 5, 0, 32, 6, 54, 1, 2, 5, 3];
sorted_data = sort(data);
dd = diff(sorted_data);
mean_dd = mean(dd);
ii = find(dd> 2*mean_dd,1,'first');
large_numbers = sorted_data(ii:end);
large_numbers =
6 16 32 54
the threshold value (2 in this case) lets you play with the meaning of "how much greater" a number has to be.
If it were me I'd use a little more statistical insight, that would give the most flexibility for the code in the future.
x = [1 2 3 2 2 1 4 6 15 83 2 4 22 81 0 8 7 7 7 3 1 2 3]
EpicNumbers = x( x>(mean(x) + std(x)) )
Then you can increase or decrease the number of standard deviations to broaden or tighten your threshold.
LessEpicNumbers = x( x>(mean(x) + 2*std(x)) )
MoreEpicNumbers = x( x>(mean(x) + 0.5*std(x)) )
A simple solution would be to use find and a treshold based on the mean value (or multiples thereof):
a = [16, 1, 1, 0, 5, 0, 32, 6, 54, 1, 2, 5, 3]
find(a>mean(a))