Sumproduct with array condition - arrays

I would like to use one sumproduct formula that relies on an array of conditions of cellvalue. So basically I want to sum something when one of the entries of some cells where found before.
I can make the array of conditions work but not by cell values. In example.
Let A1 = "a", A2 = "b", B1 = 1, B2 = 2
Then
C1 = Sumproduct((A1:A100={"a"."b"})*(B1:B100)) = 3
works fine, but
C2 = Sumproduct((A1:A100=A1:A2)*(B1:B100)) = ERROR
Is there any way to put {"a"."b"} into a cell or an set of cells?
Greetings and Thanks for your help,
Peter
Disclaimer: I know I could simply write:
C2 = Sumproduct((A1:A100=A1)*(B1:B100)) + Sumproduct((A1:A100=A2)*(B1:B100))
But I would like to have a solution that is still nice to handle if 10+ conditions are on the list.

Use COUNTIF:
=SUMPRODUCT(COUNTIF(A1:A2,A1:A100)*B1:B100)

Use TRANSPOSE to make the cyclic calculation think of A1:A2 as being in a different order (... direction?) than A1:A100 and B1:B100.
=SUMPRODUCT((A1:A100=TRANSPOSE(A1:A2))*(B1:B100))
This formula is a true array formula and requires CSE.

Related

Excel function: reference to array in cell

I have an array in cell A1 via
A1 = {=G6:J6} = {"aa"."b"."ccc".1}
Now I want to use the cell A1 for array formula in B1. Basically B1 should be
B1 = SUMPRODUKT((C6:C12)*(B6:B12=G6:J6))
But instead of the direct reference to G6:J6 I would like to use A1 instead. I just tried:
B1 = SUMPRODUKT((C6:C12)*(B6:B12=A1))
B1 = {=SUMPRODUKT((C6:C12)*(B6:B12=A1))}
But this would not work. Is there a way to make it work?
Greetings,
Peter
For questions that appeared:
Cells G6:J6 are input data for example article numbers. I want to setup the input data only once in my sheet so I have to update less data. entries in G6:J6 are strings or numbers. Let's say G6 = "aa", H6 = "b", I6 = "ccc" and J6 = 1.
Cell B1 is one point where I need to use the data. It would rather be in another sheet but for simpler examples let's assume it is cell B1. In B1 I could of course refer to G6:J6 but this makes formular less easy to read. Therefore I would like to put a reference A1 next to B1 so one can see easily what data B1 uses.
C6:C12 is some numbers and B6:B12 is some strings/numbers that maybe match G6:J6. So sumproduct should sumup the matches.
Your cell A1 contains an array formula or array range but it only contains a single value from that array or range (each Excel cell can only contain a single result value).
So you need to replace the A1 in your SUMPRODUCT with an array or range expression.
Cell A1 value shall be G6:J6
G6:J6 populated as required with {"aa","bb","ccc",1} then in B1 put following formula and check if this is what you need.
=SUMPRODUCT(C6:C12*ISNUMBER(SEARCH(B6:B12,INDIRECT(A1))))

Ignore blank parameters in Excel array formula

I'm using an array formula to return sums and counts on a large data set.
The array formula can have up to 3 arguments but the formula needs to accommodate when any or all of the arguments are <blank>, WITHOUT using VBA.
For example
A1 = "Australia"
B1 = "Finance"
C1 = "Female"
D1 contains the formula
D1 = {count(if((region=A1)*(sector=B1)*(gender=C1),population))}
Sometimes one of the criteria will be blank
A1 = "Australia"
B1 = <blank>
C1 = "Male"
In this case I'd like the formula to return the equivalent of:
D1 = {count(if((region=A1)*(gender=C1),population))}
In the extreme case A1, B1 and C1 could be all blank in which case the formula in D1 should return the equivalent of Count(population)
Is there a way to create an array formula that accounts for these possibilities? I originally tried to create a dynamic argument string
E1 = "(region=A1)*(sector=B1)*(gender=C1)"
and then use the string as the argument within the array formula
D1 = {count(if(E1,population))}
but I could find a way to get this to work.
I've tried a number of solutions, but there is always a key element missing. By using isblank I can determine if the cell is blank, but in order for this to be useful I'd need to turn this returned value into an array of boolean values of length count(population).
Any and all ideas are greatly appreciated.
Thanks.
Have you tried Nz() ? Encapsulate your current code with that and give it a try. I've had issues with blanks/nulls here and there myself.
Another option could be the IIF() statement. But that might not do what you want it to. Here are reference links:
Nz: http://www.techonthenet.com/access/functions/advanced/nz.php
IIF: http://www.techonthenet.com/access/functions/advanced/iif.php
You don't need VBA and you also don't even need an array formula. You can use SUMPRODUCT() with wildcards.
Say we have:
In A2 enter:
=IF(A1="","*",A1)
and copy across. This will display either an asterisk or the value above.
Then use:
=SUMPRODUCT(ISNUMBER(SEARCH(A2,G1:G10,1))*ISNUMBER(SEARCH(B2,H1:H10,1))*ISNUMBER(SEARCH(C2,I1:I10,1)))
This is a way to get SUMPRODUCT() to accept the asterisk as a wildcard:

Searching an Array of Cells in Excel

I am trying to search an array of cells in excel to find if it contains a word to then further evaluate.
so for example; I have named the array (A1:A5) as 'cList'.
A1 = apple
A2 = pear
A3 = orange
A4 = banana
A5 = cherry
I want to
=SEARCH("pear",cList)
but i keep getting FALSE - which is not true because it is contained in A2.
My thought here is that Search cannot be used on an array, because if I instead used
=SEARCH("pear",A2)
I will get my desired TRUE.
So is there another way to test an array if it contains and answer?
SEARCH only searches a single cell. The easiest way to find if a range contains a word is just to use COUNTIF
=COUNTIF($A$1:$A$5,"pear")
This tells you how many matches there are, or to get it as a TRUE/FALSE value
=COUNTIF($A$1:$A$5,"pear")>0
You can also use wildcards, so this would find things like "pearmain" and "prickly pear"
=COUNTIF($A$1:$A$5,"*pear*")>0
Sounds like a for loop would work fine...
for(int i=1; i<6; i++){
String cell = "A" + i;
if(SEARCH("pear",cell)
//do things...
}
EDIT: Rereading your question, you'd want to adapt this to loop over your array...

Multiply elements in second column according to labels in the first

I'm working in Matlab.
I have a two-dimensional matrix with two columns. Lets consider elements in the first column as labels. Labels may be repeated.
How to multiply all elements in the second column for every label?
Example:
matrix = [1,3,3,1,5; 2,3,7,8,3]'
I need to get:
a = [1,3,5; 16,21,3]'
Can you help me with doing it without for-while cycles?
I would use accumarray. The preprocessing with unique assigns integer indices 1:n to the values in the first row, which allow accumarray to work without creating unnecessary bins for 2 and 4. It also enables the support for negative numbers and floats.
[ulable,~,uindex]=unique(matrix(:,1))
r=accumarray(uindex,matrix(:,2),[],#prod)
r=[ulable,r]
/You can also use splitapply:
[ulable,~,uindex]=unique(matrix(:,1))
r=splitapply(#prod,matrix(:,2),uindex)
r=[ulable,r]
You can do it without loops using accumarray and the prod function:
clear
clc
matrix = [1,3,3,1,5; 2,3,7,8,3]';
A = unique(matrix,'rows');
group = A(:,1);
data = A(:,2);
indices = [group ones(size(group))];
prods = accumarray(indices, data,[],#prod); %// As mentionned by #Daniel. My previous answer had a function handle but there is no need for that here since prod is already defined in Matlab.
a = nonzeros(prods)
Out = [unique(group) a]
Out =
1 16
3 21
5 3
Check Lauren blog's post here, accumarray is quite interesting and powerful!
Try something like this, I'm sure it can be improved...
unValues = unique(matrix(:,1));
bb = ones(size(unValues));
for ii = 1:length(unValues)
bb(ii) = bb(ii)*prod(matrix(matrix(:, 1) == unValues(ii), 2));
end
a = [unValues bb];

Retrieve first value from cell array of cells

I have a cell array of cell arrays...
data = {1x16}
{1x16}
{1x16}
and I am trying to retrieve the first value from each of the cells.. However when I do
data{:}(1)
I end up with an error saying
Bad cell reference operation.
First of all is there a good reason as to why I shouldn't be allowed to do this? And secondly is there a way around this?
Cheers!
Ben
For a 1D cell array -
first_vals = arrayfun(#(n) data{n}(1),1:numel(data))
This should work for a general case -
first_vals = reshape(arrayfun(#(n) data{n}(1),1:numel(data)),size(data))
I would prefer doing it using a simple for loop :
For instance, this would work :
data = [{[1:16]}; {[17:32]}; {[33:48]}];
b= []
for i=1:length(data)
b = [b data{i,1}(1)];
end

Resources