Matlab programming, Matrix sorting and ranking - matlab

Consider an example given below. There are 3 customers A, B,C.
1st row of matrix is the demand of respective customer and second row is the day when they need.
for example: demand A=[10,40,50;15,45,75]; Customer A needs 10 items on 15th day.. 40 items on 45th day and 50 items on 75th day..Similarly for B,C.
demand A=[10,40,50;15,45,75];
demand B=[80,30,20;05,35,80];
demand C=[50,40,30;20,47,88];
Now i need to rank the customer on basis of days. So here answer should be like
rank 1: 5th day customer B 80 items
rank 2: 15th day customer A 10 items
rank 3: 20th day customer C 50 items.
and so on.
How can i do it in mat lab. so that when i rank it on basis of the day then I should then know how many items and which customer accordingly.
output should be like this:
Rank Customer items day
1 B 80 05
2 A 10 15
3 C 50 20
4 B 30 35
5 A 40 45
6 C 40 47
7 A 40 75
8 B 20 80
9 C 30 88

I suggest the following approach:
First stage
generates a new matrix, which is the composition of A,B and C, such that:
The first col represents the day.
The second col represents the requested amount.
The third col is the costumer index (A=1,B=2,C=3).
res = [A',ones(size(A',1),1);B',ones(size(A',1),1)*2;C',ones(size(C',1),1)*3];
res(:,[2,1]) = res(:,[1,2]);
Second stage
sort the matrix according to the first column, which represents the day
[~,sortedDaysIndices] = sort(res(:,1));
res = res(sortedDaysIndices,:);
Third stage: print the results
for ii=1:size(res)
if res(ii,3)==1
costumerStr = 'A';
elseif res(ii,3)==2
costumerStr = 'B';
else
costumerStr = 'C';
end
fprintf('%s\n',[num2str(ii) ' ' costumerStr ' ' num2str(res(ii,2)) ' ' num2str(res(ii,1))])
end
Result
1 B 80 5
2 A 10 15
3 C 50 20
4 B 30 35
5 A 40 45
6 C 40 47
7 A 50 75
8 B 20 80
9 C 30 88

Related

how to use parameter with calculated field

person quantity
A 2
B 3
C 4
D 5
E 8
F 10
G 15
H 20
I 55
J 30
K 21
L 4
M 6
N 10
O 25
P 22
No of people having quantity <25
No of people having quantity >25
please help for the above questions
First what you need to do is make a parameter of the type string:
Then you make a field that is working from the values set in the parameter. Use a case statement which has the logic "If the parameter is x, do this; if y do this"
For the "do this" part, you can use an if statement as well:
CASE [Quantity Paramter]
WHEN ">= 25 Quantity" THEN IF [Quantity] >= 25 THEN [Person] END
WHEN "< 25 Quantity" THEN IF [Quantity] < 25 THEN Person END
END
This newly created field is your new Person field and so you should drag that onto the Columns or Rows pills
Make sure to exclude the null values by using a filter on your new field. The null values in this context are the values that are not satisfying what you've chosen in the parameter. So if you've selected >=25, then a person with 2 would be a null
The below is demonstrating it working with the sample data:
Person Quantity
A 3
B 57
C 4
D 5
E 10
F 50
G 7
H 3
I 2

how to look back on rows until criteria matched

Consider the following sheet example:
A1 A2
1 5 10
2 6 12
3 -3 9
4 1 10
5 5 15
6 -4 11
7 9 20
How do I look back from row 6 and sum all A2 rows until a previous negative A1 row.
In this example: 15 + 10 = 25
Assuming -3 is in A3, in C4 and copied down to suit:
=IF(A3<0,0,C3+B3)
This creates a running total, starting immediately after the first negative in the left hand column, that resets after each negative in the left hand column.

Counting number of items in a matrix according a period of time

I have a little issue.
For example, I have a matrix
m=[11 1 9 ;
22 2 10;
33 3 11;
44 4 14;
55 1 15;
66 4 20;
77 1 20;
88 1 24;
99 2 24 ]
where the first column is the id of a product, the second column is the id of the buyer, and the third is the day of purchase.
I would like to count the number of articles bought by a buyer for a period delta=5 days.
I tried this code but I have an issue: I would like to obtain a final matrix where in the rows i have the ids of the users and in columns the number of articles bought for each period.
m=[11 1 9 ;22 2 11; 33 3 10; 44 4 15; 55 1 15;66 4 20; 77 1 20; 88 1 24; 99 2 24 ]
D=m(:,3)
p=0;
delta=5
res=zeros(length(unique(m(:,2))),(div(max(D),delta)))
NbA=zeros(1,length(unique(m(:,2))))
while p<max(D)+1
p
pos=find((m(:,3)>=p)& (m(:,3)<p+delta))
Mtemp=u(pos,:);
[r c]=size(Mtemp);
Ustemp=Mtemp(:,2);
UnUstemp=unique(Ustemp);
for i=1:length(UnUstemp)clc
us=UnUstemp(i);
[n l]=size(find(Ustemp==us));
NbA(i)=n;
end
res=[res ;NbA];
p=p+delta;
end

Sorting data in MATLAB dependant on one column

How do I sort a column based on the values in another column in MATLAB?
Column A shows position data (it is neither ascending or descending in order) Column B contains another column of position data. Finally column C contains numerical values. Is it possible to link the first position value in B with its numerical value in the first cell of C? Then after this I want to sort B such that it is in the same order as column A with the C values following their B counterparts?The length of my columns would be 1558 values.
Before case;
A B C
1 4 10
4 1 20
3 5 30
5 2 40
2 3 50
After Case;
A B C
1 1 20
4 4 10
3 3 50
5 5 30
2 2 40
Basically A and B became the same and Column C followed B.
Since you don't want things necessarily in ascending or descending order, I don't think any built-in sorting functions like sortrows() will help here. Instead you are matching elements in one column with elements in another column.
Using [~,idx]=ismember(A,B) will tell you where each element of B is in A. You can use that to sort the desired columns.
M=[1 4 10
4 1 20
3 5 30
5 2 40
2 3 50];
A=M(:,1); B=M(:,2); C=M(:,3);
[~,idx]=ismember(A,B);
sorted_matrix = [A B(idx) C(idx)]
Powerful combo of bsxfun and matrix-multiplication solves it and good for code-golfing too! Here's the implementation, assuming M as the input matrix -
[M(:,1) bsxfun(#eq,M(:,1),M(:,2).')*M(:,2:3)]
Sample run -
>> M
M =
1 4 10
4 1 20
3 5 30
5 2 40
2 3 50
>> [M(:,1) bsxfun(#eq,M(:,1),M(:,2).')*M(:,2:3)]
ans =
1 1 20
4 4 10
3 3 50
5 5 30
2 2 40
Given M = [A B C]:
M =
1 4 10
4 1 20
3 5 30
5 2 40
2 3 50
You need to sort the rows of the matrix excluding the first column:
s = sortrows(M(:,2:3));
s =
1 20
2 40
3 50
4 10
5 30
Then use the first column as the indices to reorder the resulting submatrix:
s(M(:,1),:);
ans =
1 20
4 10
3 50
5 30
2 40
This would be used to build the output matrix:
N = [M(:,1) s(M(:,1),:)];
N =
1 1 20
4 4 10
3 3 50
5 5 30
2 2 40
The previous technique will obviously only work if A and B are permutations of the values (1..m). If this is not the case, then we need to find the ranking of each value in the array. Let's start with new values for our arrays:
A B C
1 5 60
6 1 80
9 6 60
-4 9 40
5 -4 30
We construct s as before:
s = sortrows([B C]);
s =
-4 30
1 80
5 60
6 60
9 40
We can generate the rankings one of two ways. If the elements of A (and B) are unique, we can use the third output of unique as in this answer:
[~, ~, r] = unique(A);
r =
2
4
5
1
3
If the values of A are not unique, we can use the second return value of sort, the indices in the original array of the elements in sorted order, to generate the rank of each element:
[~, r] = sort(A);
r =
4
1
5
2
3
[~, r] = sort(r);
r =
2
4
5
1
3
As you can see, the resulting r is the same, it just takes 2 calls to sort rather than 1 to unique. We then use r as the list of indices for s above:
M = [A s(r, :)];
M =
1 1 80
6 6 60
9 9 40
-4 -4 30
5 5 60
If you must retain the order of A then use something like this
matrix = [1 4 10; 4 1 20; 3 5 30; 5 2 40; 2 3 50];
idx = arrayfun(#(x) find(matrix(:,2) == x), matrix(:,1));
sorted = [matrix(:,1), matrix(idx,2:3)];

Matlab isn't incrementing my variable

I have the following matrix declared in Matlab:
EmployeeData =
1 20 100000 42 14
2 15 95000 35 14
3 18 70000 28 14
4 10 85000 35 14
5 10 40000 21 12
6 4 45000 14 8
7 3 50000 21 10
8 5 55000 21 14
9 1 25000 14 7
10 2 50000 21 9
42 4 100000 42 10
Where column 1 represents ID numbers, 2 represents years, 3 is salary, 4 is vacation days, and 5 is sick days. I am trying to find the maximum value of a column (in this case the salary column), and print out the ID associated with that value. If more than one employee has the maximum value, all the IDs with that maximum are supposed to be shown. So here is how I naively implemented a way to do it:
>> maxVal = [];
>> j = 1;
>> for i = EmployeeData(:, 3)
if i == max(EmployeeData(:, 3))
maxVal = [maxVal EmployeeData(j, 1)];
end
j = j + 1;
end
But it shows maxVal to be [] in my workspace variables, instead of [1 42] as I expected. Upon inserting a disp(i) in the for loop above the if to debug, I get the following output:
100000
95000
70000
85000
40000
45000
50000
55000
25000
50000
Just like I expected. But when I switch out that disp(i) with a disp(j), I get this for my output:
1
What am I doing wrong? Should this not work?
MATLAB for loops operate on rows, not columns. You should try replacing your for loop with:
for i = EmployeeData(:, 3)' % NOTE THE TRANSPOSE
...
end
EDIT: Note that you can do what you're trying to do without a forloop:
maxVal = EmployeeData(EmployeeData(:,3) == max(EmployeeData(:,3)),1);
Is this what you want?
>> EmployeeData(EmployeeData(:,3)==max(EmployeeData(:,3)),1)
ans =
1
42