I was wondering, let's say we have a table with eg 4 columns that has all possible combinations of numbers between 0 and 2. So it would be
0 0 0 0
0 0 0 1
0 0 0 2
0 0 1 0
0 0 1 1
0 0 1 2
0 0 2 0
0 0 2 1
0 0 2 2
0 1 0 0
0 1 0 1
and so on containing 3^4 rows.
Is there a way for me to find the combination in lets say row 56 without having to construct the whole table, as it is impossible to create a table like this for bigger numbers (eg values ranging from 0 to 100 using >1000 columns).
The rightmost column of row n is simply mod(n, 3).
If you then replace n with floor(n./3) you can retrieve the next rightmost in the same way.
Rinse and repeat to construct the entire row...
Each combination is the base-3 expansion of a number, starting from 0 and ending in 3^4-1. So you can use dec2base to convert from that number to its expansion:
N = 3; %// number of digits
M = 4; %// number of columns
n = 56; %// row number: 1, 2, ..., N^M
result = dec2base(n-1,N)-'0';
This -
%%// Given data
rownum = 56; %%// Row number to be found out
arr1=[0 1 2]; %%// Numbers used for perms
Nc = 4; %%// Number of columns
N = numel(arr1);%%// Number of array elements for perms
%%// Combination needed
comb1 = arr1(fliplr(ceil(bsxfun(#mod,rownum,power(N,1:Nc))./power(N,0:Nc-1))))
Output -
comb1 =
2 0 0 1
Related
I have a time-series matrix X whose first column contains user ID and second column contains the item ID they used at different times:
X=[1 4
2 1
4 2
2 3
3 4
1 1
4 2
5 3
2 1
4 2
5 4];
I want to find out which user used which item how many times, and save it in a matrix Y. The rows of Y represent users in ascending order of ID, and the columns represent items in ascending order of ID:
Y=[1 0 0 1
2 0 1 0
0 0 0 1
0 3 0 0
0 0 1 1]
The code I use to find matrix Y uses 2 for loops which is unwieldy for my large data:
no_of_users = size(unique(X(:,1)),1);
no_of_items = size(unique(X(:,2)),1);
users=unique(X(:,1));
Y=zeros(no_of_users,no_of_items);
for a=1:size(A,1)
for b=1:no_of_users
if X(a,1)==users(b,1)
Y(b,X(a,2)) = Y(b,X(a,2)) + 1;
end
end
end
Is there a more time efficient way to do it?
sparse creates a sparse matrix from row/column indices, conveniently accumulating the number of occurrences if you give a scalar value of 1. Just convert to a full matrix.
Y = full(sparse(X(:,1), X(:,2), 1))
Y =
1 0 0 1
2 0 1 0
0 0 0 1
0 3 0 0
0 0 1 1
But it's probably quicker to just use accumarray as suggested in the comments:
>> Y2 = accumarray(X, 1)
Y2 =
1 0 0 1
2 0 1 0
0 0 0 1
0 3 0 0
0 0 1 1
(In Octave, sparse seems to take about 50% longer than accumarray.)
I have a matrix filled with zeros and ones and I need to count the number of ones in each row. Then I need to know which row's count exceeds or equal a specific limit (any number, for example 3). After that foreach row in these rows I need to create a vector that holds the index of all the columns which has non-zero values in that row and in all the rows above it and below it till it reach a row with zero count.
Example:
data contains the data below:
0 0 0 0 0 0 0
0 0 0 1 1 0 0
0 1 0 0 1 0 1
0 0 0 0 0 0 0
0 1 0 0 0 0 0
0 1 1 1 0 0 0
0 0 1 0 0 0 0
0 0 0 0 0 0 0
The output should be if the limit is 3:
Row 3: col 4 5 2 5 7
Row 6: col 2 2 3 4 3
I already read the data and I counted the ones in the code below:
load('data');
mat(isnan(mat)) = 0;
[rows,cols,vals] = find(mat~= 0);
unqRows=unique(rows);
countElinRows=histc(rows,unqRows);
Edit for clarification as requested by commentators:
If the third row of the given sample input array becomes [0 1 0 0 0 0 1], then we must only have this output -
Row 6: col 2 2 3 4 3
Assuming A as the input array, see if this works for you -
[sc1,sr1] = find(A') %//'# row and col indices for sorted rows
s_a1 = sum(A,2) %// sum input array along cols
bounds = find(s_a1==0) %// find bounds/gropus delimited by all zero rows
bounds = unique([1 ; bounds ; size(A,1)]) %// account for non all zero
%// starting and ending rows
cumsum1 = cumsum(s_a1==0) + double(sum(A(1,:))~=0) %// label groups
valid_groups = accumarray(cumsum1, s_a1, [], #max)>=3 %// valid groups
out = arrayfun(#(k1) sc1(sr1>=bounds(k1) & sr1<=bounds(k1+1)),...
1:numel(bounds)-1,'un',0) %// find all indices within each group
out = out(valid_groups) %// select only the valid groups for the final output
Visualized output with celldisp(out).
Apologies for strange code, but it's the best I could come up with
[I1,~]=find(sum(mat,2)>=3)
[I2,~]=find(sum(mat,2)==0)
[~,CM]=find(diff(mod(sum(bsxfun(#le,I1,I2.')),2))~=0)
[I,J]=arrayfun(#(t)find(mat(I2(CM(t)):I2(CM(t)+1),:)>0),1:length(CM),'UniformOutput',false)
[~,w]=cellfun(#sort,I,'UniformOutput',false);
J=arrayfun(#(t) J{t}(w{t}).',1:length(J),'UniformOutput',false)
celldisp(J)
This code does feel pretty overcomplicated.
I have tested it on a few cases and it seems to be fine, but it's hard to know for certain.
This question already has answers here:
Construct this matrix based on two vectors MATLAB
(3 answers)
Closed 8 years ago.
I have a vector y = [0; 2; 4]
I want to convert each element of it into vector, where all elements are zero but element with index equal to digit is 1.
I'd like to do it without loops.
For example [0; 2; 4] should be converted to
[1 0 0 0 0 0 0 0 0 0;
0 0 1 0 0 0 0 0 0 0;
0 0 0 0 1 0 0 0 0 0]
(in this example vector first index is 0)
The usual trick with sparse can be used to simplify the process. Let n denote the desired number of columns. Then
result = full(sparse(1:numel(y), y+1, 1, numel(y), n));
For example, y = [0;2;4] and 10 produce
result =
1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
First you need to decide how many digits you want to represent each number. In your case, you have 10 digits per number, so let's keep that in mind.
Once you do this, it's just a matter of indexing each element in your matrix. In your case, you have 10 digits per number. As such, do something like this:
y = [0; 2; 4]; %// Your digits array
out = zeros(numel(y), 10); %// 10 digits per number
ind = sub2ind(size(out), [1:numel(y)].', y+1);
out(ind) = 1;
The output should look like this:
out =
1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
Let's go through this code slowly. y defines the digits you want per row of the output matrix. out allocates a matrix of zeroes where the number of rows is defined by how many digits you want in y. out will thus store your resulting matrix that you have shown us in your post.
The number of columns is 10, but you change this to be whatever you want. ind uses a command called sub2ind. This allows to completely vectorize the assignment of values in your out matrix and avoids a for loop. The first parameter is an array of values that defines how many rows and columns are in your matrix that you are trying to assign things to. In this case, it's just the size of out. The second and third parameters are the rows and columns you want to access in your matrix. In this case, the rows vary from 1 to as many elements as there are in y. In our case, this is 3. We want to generate one number per row, which is why it goes from 1 to 3. The columns denote where we want to set the digit to one for each row. As MATLAB indexes starting at 1, we have to make sure that we take y and add by 1. ind thus creates the column-major indices in order to access our matrix. The last statement finally accesses these locations and assigns a 1 to each location, thus producing our matrix.
Hope this helps!
Per my previous question couple days ago, now, I have several mx3 matrices with rows from (0,1,num), (-1,0,num), (0,1,num), (0,-1,num), (1,1,num), (-1,1,num), (1,-1,num),(-1,-1,num), where num is an integer which can take any values between 0 to 3.
I would like to create a new matrix, with 8 rows, and 6 columns, where the the first two columns represent each of the above coordinates, and each of the remaining columns indicate the frequency
of each of the above coordinates at each num values. i.e. columns 3 of each row indicates the number of times we see the coordinate corresponding to that row with and num=0. columns 4 of each row indicates the number of times we see the coordinate corresponding to that row with and num=1.
columns 5 of each row indicates the number of times we see the coordinate corresponding to that row with and num=2, and columns 6 of each row indicates the number of times we see the coordinate corresponding to that row with and num=3.
For instance, if A=[0 1 1
1 1 1
1 1 0
1 0 0
1 1 0
1 1 0
1 1 0
1 1 0
1 1 0
1 -1 0
1 1 0
1 1 3
1 1 2
1 1 3
1 1 3]
I would like to see something like:
-1 -1 0 0 0 0
-1 0 0 0 0 0
-1 1 0 0 0 0
0 -1 0 0 0 0
0 1 0 1 0 0
1 -1 1 0 0 0
1 0 1 0 0 0
1 1 7 1 1 3
Is there a way to do it? Thanks.
Try this:
counts = zeros(9, 6); % Initialize output matrix
k = 1;
for ii = -1:1
for jj = -1:1
ijCoords = (A(:,1) == ii) & (A(:,2) == jj); % Find rows containing coordinate (ii,jj)
ijCount = histc(A(ijCoords,3), 0:3); % Count how many 0,1,2,3 in these rows
counts(k,:) = [ii, jj, ijCount(:)']; % Add the counts to the next row of the output matrix
k = k + 1;
end
end
counts(5, :) = []; % Remove coordinate (0,0) because you don't want it.
I have a matrix A which contains values 0-100. Matrix B (same number of rows, but only two columns) has values 0 or 1 in its second column. Matrix C has the same number of entries as Matrix A, but just 0 or 1.
I'll assume C starts full of zeros. If there is a 1 in the second column of B, then I want to have a 1 in the same row in C, for every position where there is a value in the corresponding position in A. However, I can't work out how to get this. I've tried using the for loop, but it doesn't seem to be doing what I want.
i.e.
A =
10 10 10
10 10 10
0 20 10
B =
1 0
2 0
3 1
I want to have C:
C =
0 0 0
0 0 0
0 1 1
Very grateful for any help.
Find desired rows using B:
>> B(:, 2) == 1
ans =
0
0
1
Find possible values from A:
>> A ~= 0
ans =
1 1 1
1 1 1
0 1 1
Put it all together by anding using bsxfun:
>> bsxfun(#and, B(:, 2) == 1, A ~= 0)
ans =
0 0 0
0 0 0
0 1 1