Array subtraction in Google Sheets - arrays

I have two arrays and I want a resulting array that's the vector difference.
A1:A10 and B1:B10 have numeric values, and I want {A1:A10}-{B1:B10}, but that just gives me A1-B1, not the full array. Is there a subtraction operator for arrays?
Example Sheet:
https://docs.google.com/spreadsheets/d/1rjh_mkpZdz7LX4V0obxEmfRLdZ2CoTIjdpxVLHYBD5s/edit#gid=0
I want the result in D1 without the extra column C

use ArrayFormula:
=ARRAYFORMULA(A1:A10-B1:B10)
or shorter Index:
=INDEX(A1:A10-B1:B10)
or longer Query:
=QUERY(A1:B10, "select A-B label A-B''", 0)

Related

Multiply two ranges in Excel to get an array result

Excel 365 allows to multiply ranges to get an array as a result.
Example:
#
A
B
C
1
1
0
1
2
0
1
1
Entering in A3
= A1:C1 * A2:C2
will evaluate to {1,0,1} * {0,1,1}
and return an array {0,0,1} spilling in A3:C3
#
A
B
C
3
0
0
1
This operation can also be used in formulas, especially useful in FILTER(), SUMPRODUCT() etc.
Is there a formula in Excel 365 that can take as arguments an arbitrary number of 1-D ranges, multiply them, and return a 1-D array in the same way as above?
For what I found out so far, SUMPRODUCT() and MMULT() can return only a single value, not a 1-D array.
Alternatively, I can write a LAMBDA, but would like to avoid it, if there is a ready-made formula for it.
I am not 100% what do you mean, I would assume you want to multiply all rows of the same column and return a row array with the result per column. You can achieve it in cell E1 using the following formula:
=BYCOL(A1:C3, LAMBDA(col, PRODUCT(col)))
and here is the output:
If you have only positives numbers, then you can use MMULT, based on the following mathematical properties:
Putting in excel terms using EXP/LN functions in our case it would be:
=EXP(MMULT(TOROW(ROW(A1:C3)/ROW(A1:C3)), LN(A1:C3)))
or using LET to avoid repetitions:
=LET(rng, A1:C3, rows, ROW(rng), u, TOROW(rows/rows), EXP(MMULT(u, LN(rng))))
You get the same result.
Note: rows/rows just returns the unit vector with the same number of rows as A1:C3.

array based sumif in excel by formula

So I m trying to find some alternative to sumifs in excel where each condition needs to be checked in a 2D range instead of a 1D range.
For example, in the below table I want the sum of values in column V for rows where A12 ("IJ") is present in range A2:C8 (P), B12 ("NM") is present in the range D2:F8 (S) and C12 ("XX") is present in range G2:I8 (A)
I am trying to find a solution involving an array-based formula (without VBA).
Like for example in the below-given formulas,
SUMPRODUCT((B2:B8'=A12)*J2:J8) will give an array-based calculation as follows
SUMPRODUCT({TRUE;FALSE;TRUE;FALSE;FALSE;TRUE;FALSE}*{22;79;45;67;43;72;52})
= SUMPRODUCT({22;0;45;0;0;72;0})
=139
It is easy when there is only one condition needs to be checked but like sumifs, I intend to check multiple conditions, but as soon as I add other conditions, the array becomes multidimensional and gives the wrong answer.
Example:
SUMPRODUCT((A2:C8=A12)*(D2:F8=B12)*J2:J8) breaks down to
=SUMPRODUCT(
{FALSE,TRUE,FALSE;FALSE,FALSE,FALSE;FALSE,TRUE,FALSE;FALSE,FALSE,FALSE;FALSE,FALSE,FALSE;FALSE,TRUE,FALSE;FALSE,FALSE,FALSE}*
{TRUE,FALSE,FALSE;FALSE,FALSE,FALSE;TRUE,FALSE,FALSE;FALSE,FALSE,FALSE;FALSE,FALSE,FALSE;TRUE,FALSE,FALSE;FALSE,FALSE,FALSE}
*J2:J8)
in the background what is happening is (example for 3rd row)
SUMPRODUCT( ({FALSE, TRUE ,FALSE} * {TRUE,FALSE,FALSE}) * 45 )
= SUMPRODUCT({FALSE,FALSE,FALSE} *45 )
=0
SUMPRODUCT(({FALSE,TRUE ,FALSE} + {TRUE,FALSE,FALSE}) * 45 )
= SUMPRODUCT({TRUE,TRUE,FALSE} *45 )
= 90
#expected answer =45
Can someone help me understand where I am going wrong or what I am missing?
If there is any other way then suggestions are always welcome.
Please note this is a dummy data actual data is very big for each header (P,S,A) there are values in 10 columns respectively and the number of rows is also very large.
Try this...
=SUMPRODUCT( ((A2:A8=A12)+(B2:B8=A12)+(C2:C8=A12)) * ((D2:D8=B12)+(E2:E8=B12)+(F2:F8=B12)) * ((G2:G8=C12)+(H2:H8=C12)+(I2:I8=C12)) * J2:J8 )
For SUMPRODUCT to work, the shape of the Boolean array needs to match the shape of the array you wish to conditionally sum.
J2:J8 is seven rows tall by one column wide.
The above formula creates an array of 1s and 0s from your three criteria ranges and shapes it into seven rows tall by one column wide.
At that point, SUMPRODUCT can do it's normal thing because the criteria array matches the dimension of the sum array J2:J8.

Indexing a cell array with variable number of dimensions with a vector

In MATLAB, have an N-dimensional cell C, where N is an integer only determined at runtime. How do I access a specific element of C with a vector variable id? For example, with N=3 and id=[1,5,2], how to programmatically get the content of c{1,5,2}? I cannot hard-code it as c{id(1),id(2),id(3)} since N is only fixed at runtime.
If id is a cell array, then you can use sub2ind for this by taking advantage of the comma separated list syntax ,i.e. {:}, to send a variable number of inputs to sub2ind
id = {1,5,2};
ind = sub2ind(size(C), id{:})
c{ind}
if id isn't a cell array (and for some reason can't be created as one), then use num2cell to convert it.

Split matrix into several depending on value in Matlab

I have a cell array that I need to split into several matrices so that I can take the sum of subsets of the data. This is a sample of what I have:
A = {'M00.300', '1644.07';...
'M00.300', '9745.42'; ...
'M00.300', '2232.88'; ...
'M00.600', '13180.82'; ...
'M00.600', '2755.19'; ...
'M00.600', '15800.38'; ...
'M00.900', '18088.11'; ...
'M00.900', '1666.61'};
I want the sum of the second columns for each of 'M00.300', 'M00.600', and 'M00.900'. For example, to correspond to 'M00.300' I would want 1644.07 + 9745.42 + 2232.88.
I don't want to just hard code it because each data set is different, so I need the code to work for different size cell arrays.
I'm not sure of the best way to do this, I was going to begin by looping through A and comparing the strings in the first column and creating matrices within that loop, but that sounded messy and not efficient.
Is there a simpler way to do this?
Classic use of accumarray. You would use the first column as an index and the second column as the values associated with each index. accumarray works where you group values that belong to the same index together and you apply a function to those values. In your case, you'd use the default behaviour and sum things together.
However, you'll need to convert the first column into numeric labels. The third output of unique will help you do this. You'll also need to convert the second column into a numeric array and so str2double is a perfect way to do this.
Without further ado:
[val,~,id] = unique(A(:,1)); %// Get unique values and indices
out = accumarray(id, str2double(A(:,2))); %// Aggregate the groups and sum
format long g; %// For better display of precision
T = table(val, out) %// Display on a nice table
I get this:
>> T = table(val, out)
T =
val out
_________ ________
'M00.300' 13622.37
'M00.600' 31736.39
'M00.900' 19754.72
The above uses the table class that is available from R2013b and onwards. If you don't have this, you can perhaps use a for loop and print out each cell and value separately:
for idx = 1 : numel(out)
fprintf('%s: %f\n', val{idx}, out(idx));
end
We get:
M00.300: 13622.370000
M00.600: 31736.390000
M00.900: 19754.720000

length in 2 dimension array

var example is a 2-dimension array. example.length will give values like 14.3
But how can I get an integer for the length of example in second dimension, like 3 in this case?
Thank you!
If the array is homogeneous (which is always the case when such an array is the result of a getValues() call in a spreadsheet range for example) you can simply write :
example[0].length
EDIT : a few comments to be more clear ...
The 2D array you get from example = range.getValues() is always an array of rows data.
The number of rows is represented by example.length and the inner array length (representing rows content) is always example[0].length, which is actually the number of columns

Resources