Can i do several calculations in one calculation field? - tableau-api

Can i use calculation field for a multiple simple calculations?
Can't find it in documentation
SUM([Au 1])/SUM([AU])
SUM([Be 1])/SUM([BE])
syntax error

You can reference calculations from other calculated fields, but you cannot have multiple results with the same calculated field.
The example below works:
Col 1 | Col 2 | Col 3
1.00 | 1.00 | 2.00
Calculated Field: Ratio of Col 1 & Col 2
SUM([Col 1]) / SUM([Col 2]) = 1
Calculated Field: Ratio of Col 1 & Col 3
[Ratio of Col 1 & Col 2] / SUM([Col 3]) = 0.5
The example below will not work:
Col 1 | Col 2 | Col 3
1.00 | 1.00 | 2.00
Calculated Field: Ratio of Col 1 & Col 2 & Col 3
SUM([Col 1]) / SUM([Col 2])
SUM([Col 1]) / SUM([Col 3]) = Error
You could do this instead:
Col 1 | Col 2 | Col 3
1.00 | 1.00 | 2.00
Calculated Field: Ratio of Col 1 & Col 2 & Col 3
(SUM([Col 1]) / SUM([Col 2])) / SUM([Col 3]) = 0.5
Hope this helps.

Related

value in new column if two values if two columns match two others Matlab

So i have two very long matrices. A sample is given below:
First_Matrix:
A = [...
1 1 1;
1 1 2;
1 1 3;
1 2 1;
1 2 2;
1 2 3;
1 3 1;
1 3 2;
1 3 3];
Second Matrix
B = [...
1 1 916;
1 2 653;
1 3 114];
And I would like a thirds matrix that would combine the first matrix with the third column of the second matrix, based on the values in the first two column of the 2 matrices matching (being the same).
So Ouput_Matrix:
C = [...
1 1 1 916;
1 1 2 916;
1 1 3 916;
1 2 1 653;
1 2 2 653;
1 2 3 653;
1 3 1 114;
1 3 2 114;
1 3 3 11];
What would be the best way to do this?
Thanks in advance
Use the second output of ismember with the 'rows' option to get the indices of the matching, from which you can easily build the result:
[~, ind] = ismember(A(:, [1 2]), B(:, [1 2]), 'rows');
C = [A B(ind, 3)];
The for loop isn't pretty and might slow you down if B is very long. But I don't think it's possible to avoid (edit: it seems it is).
A = [1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
1 3 1
1 3 2
1 3 3];
B = [1 1 916
1 2 653
1 3 114];
C = [A zeros(size(A,1),1)];
for i = 1:size(B,1)
C(all(B(i,1:2)==A(:,1:2),2),4) = B(i,3);
end
C =
1 1 1 916
1 1 2 916
1 1 3 916
1 2 1 653
1 2 2 653
1 2 3 653
1 3 1 114
1 3 2 114
1 3 3 114
It is possible to achieve what you want without a for loop, but it may not be the most optimal implementation:
n = size(B, 1); % number of rows in B
B_(1, :, :) = B'; % convert to 3D matrix to be able to use elementwise comparision
x = squeeze(all(bsxfun(#eq, A(:, 1:2), B_(1, 1:2,:)), 2)); % x(i, j) == 1 if row A(i, :) matches B(j, :)
index = x * (1:n)'; % row B(index(i), :) corresponds with row A(i, :)
A(:, 4) = B(index, 3); % add data to A
An alternative formulation for x, without conversion to 3D, is:
x = bsxfun(#eq, A(:, 1), B(:,1)') & bsxfun(#eq, A(:, 2), B(:,2)');
The disadvantage of this method is that it less extendable to more matching columns.

Creating a number pattern based on the length of an array

Creating a number pattern based on the length of array, the example is small just showing what it would look like if the array had a size of 5,6 or 7. (the actually length of arrays will be around 400,000)
How can I go about getting this numerical pattern. I was thinking it looked a little like Pascal's Triangle but the numbers are off.
I'm using Octave 3.8.1 which is like Matlab
example: If an array has the length of 5 the series would be
a1=[1 1 1;1 2 2;1 2 3;1 2 2;1 1 1]
a2=[1 1 1;2 2 1;3 2 1;2 2 1;1 1 1]
example: If an array has the length of 6 the series would be
a1=[1 1 1;1 2 2;1 2 3;1 2 3;1 2 2;1 1 1]
a2=[1 1 1;2 2 1;3 2 1;3 2 1;2 2 1;1 1 1]
example: If an array has the length of 7 the series would be
a1=[1 1 1 1;1 2 2 2;1 2 3 3;1 2 3 4;1 2 3 3;1 2 2 2;1 1 1 1]
a2=[1 1 1 1;2 2 2 1;3 3 2 1;4 3 2 1;3 3 2 1;2 2 2 1;1 1 1 1]
See image below:
This should be quite fast:
n = 9;
a1 = bsxfun(#min, min(1:n,n:-1:1).', 1:ceil(n/2));
a2 = a1(:,end:-1:1);
This does what you want:
n = 7;
a1 = cumsum(tril(ones(ceil(n/2))), 2);
a1 = a1([1:end end-mod(n,2):-1:1],:);
a2 = fliplr(a1);
A slighty different approach:
For m = ceil(n/2); the bsxfun can be substituted by
X = gallery('minij',m);
which is equal to:
X = bsxfun(#min, 1:m,(1:m).')
so you get a single block and you just need to concatenate the output.
a1 = [X; flipud(X)]
if n ~= 2*m; a1(m,:) = []; end %// clear one row if necessary
a2 = fliplr(a1)
for n = 6 you get
a1 =
1 1 1
1 2 2
1 2 3
1 2 3
1 2 2
1 1 1
and a2 accordingly mirrored. and for n = 5
a1 =
1 1 1
1 2 2
1 2 3
1 2 2
1 1 1

Legend entries not working in matlab

I am having trouble getting legend entries for a scatter plot in matlab.
I should have four different entries for each combination of two colors and two shapes.
colormap jet
x = rand(1,30); %x data
y = rand(1,30); %y data
c = [1 2 2 1 1 1 1 2 2 1 1 1 1 1 2 2 1 1 1 2 2 1 1 1 1 1 2 2 1 1]; %color
s = [2 2 1 1 1 2 1 2 2 1 1 1 1 2 2 2 1 1 1 1 2 2 1 1 1 2 2 1 1 2]; %shape
%index data for each shape (s)
s1 = s == 1; %square
s2 = s == 2; %circle
xsq = x(s1);
ysq = y(s1);
csq = c(s1);
xcirc = x(s2);
ycirc = y(s2);
ccirc = c(s2);
%plot data with different colors and shapes
h1 = scatter(xsq, ysq, 50,csq,'s','jitter','on','jitterAmount',0.2);
hold on
h2 = scatter(xcirc, ycirc, 50, ccirc, 'o','jitter','on','jitterAmount',0.2);
This plots a scatter plot with red circles and squares and blue circles and squares. Now I want a legend (this doesn't work).
%legend for each combination
legend([h1(1) h1(2) h2(1) h2(2)],'red+square','red+circle','blue+square','blue+circle')
Any ideas? Thanks :)
scatter is very limited when you want to place more than one set of points together. I would use plot instead as you can chain multiple sets in one command. Once you do that, it's very easy to use legend. Do something like this:
colormap jet
x = rand(1,30); %x data
y = rand(1,30); %y data
c = [1 2 2 1 1 1 1 2 2 1 1 1 1 1 2 2 1 1 1 2 2 1 1 1 1 1 2 2 1 1]; %color
s = [2 2 1 1 1 2 1 2 2 1 1 1 1 2 2 2 1 1 1 1 2 2 1 1 1 2 2 1 1 2]; %shape
%index data for each shape (s)
s1 = s == 1; %square
s2 = s == 2; %circle
c1 = c == 1; %circle colour %// NEW
c2 = c == 2; %square colour %// NEW
red_squares = s1 & c1; %// NEW
blue_squares = s1 & c2; %// NEW
red_circles = s2 & c1; %// NEW
blue_circles = s2 & c2; %// NEW
plot(x(red_squares), y(red_squares), 'rs', x(blue_squares), y(blue_squares), 'bs', x(red_circles), y(red_circles), 'ro', x(blue_circles), y(blue_circles), 'bo');
legend('red+square','blue+square','red+circle','blue+circle');
What's important is this syntax:
red_squares = s1 & c1;
blue_squares = s1 & c2;
red_circles = s2 & c1;
blue_circles = s2 & c2;
This uses logical indexing so that we select those circles and squares that belong to one colour or another colour. In this case, we choose only those shapes that are square and that belong to the first colour. There are four different combinations:
s1, c1
s1, c2
s2, c1
s2, c2
We get:

match IDs + find a number within a matrix in Matlab

I am facing a problem in matching elements in 2 matrices. The first element can be matched using ismember but the second element should be within a range. Please see the example below:
% col1 is integerID, col2 is a number. -->col1 is Countrycode, col2 is date
bigmat = [ 600 2
600 4
800 1
800 5
900 1] ;
% col1 is integerID, col2 is VALUE, col2 is a range -->value is Exchange rate
datamat = {...
50 0.1 [2 3 4 5 6] % 2:6
50 0.2 [9 10 11] % 9:11
600 0.01 [1 2 3 4] % 1:4
600 0.2 [8 9 10] % 8:10
800 0.12 [1] % 1:1
800 0.13 [3 4] % 3:4
900 0.15 [1 2] } ; % 1:2
I need the answer as:
ansmat = [ 600 2 0.01
600 4 0.01
800 1 0.12
800 5 nan % even deleting this row is fine
930 1 0.15 ] ;
For simplicity:
All intIDs from matrix_1 exist in matrix_2.
The numbers in range are dates! Within a range, these numbers are consecutive: [1 2...5]
For any ID, dates in the next row are not continuous. Eg, you can see [1 2 3 4] and then [8 9 10] in next row.
bigmat is a huge matrix! 300,000-500,000 rows and so a vectorized code would be appreciated. datamat is roughly 5000 rows or less. You can convert the cell to matrix. For each row, I have the minimum and maximum. The 3 column is minimum:maximum. Thanks!
Here is one possible implementation:
%# data matrices
q = [
600 2
600 4
800 1
800 5
900 1
];
M = {
50 0.1 [2 3 4 5 6]
50 0.2 [9 10 11]
600 0.01 [1 2 3 4]
600 0.2 [8 9 10]
800 0.12 [1]
800 0.13 [3 4]
900 0.15 [1 2]
};
%# build matrix: ID,value,minDate,maxDate
M = [cell2num(M(:,1:2)) cellfun(#min,M(:,3)) cellfun(#max,M(:,3))];
%# preallocate result
R = zeros(size(M,1),3);
%# find matching rows
c = 1; %# counter
for i=1:size(q,1)
%# rows indices matching ID
ind = find( ismember(M(:,1),q(i,:)) );
%# out of those, keep only those where date number is in range
ind = ind( M(ind,3) <= q(i,2) & q(i,2) <= M(ind,4) );
%# check if any
num = numel(ind);
if num==0, continue, end
%# extract matching rows
R(c:c+num-1,:) = [M(ind,1) repmat(q(i,2),[num 1]) M(ind,2)];
c = c + num;
end
%# remove excess
R(c:end,:) = [];
The result as expected:
>> R
R =
600 2 0.01
600 4 0.01
800 1 0.12
900 1 0.15
I'm not completely sure I understand .. should the second entry be '600 4 0.02'?
Anyways, you may be able to try something like:
% grab first column
col = bigmat(:, 1);
% find all entries in column that are equal to ID
rel = (col == id);
% retrieve just those rows
rows = bigmat(rel, :);
Then once you have the rows you need from your matrices, you can concatenate them together like so:
result = [rowsA(1:3) rowsB(2) rowsC(5:6)];

How do I divide the rows of a matrix by different values in MATLAB (array division)

Lets said I have the matrix M = ones(3); and I want to divide each row by a different number, e.g., C = [1;2;3];.
1 1 1 -divide_by-> 1 1 1 1
1 1 1 -divide_by-> 2 = 0.5 0.5 0.5
1 1 1 -divide_by-> 3 0.3 0.3 0.3
How can I do this without using loops?
Use right array division as documented here
result = M./C
whereas C has the following form:
C = [ 1 1 1 ; 2 2 2 ; 3 3 3 ];
EDIT:
result = bsxfun(#rdivide, M, [1 2 3]'); % untested !