I have no clue why summing over the array formula doesn't return correct results. The formula is:
=SUM(INDEX($C$4:$C$12,TRANSPOSE(OFFSET(K17,0,0,1,COUNT(K17:S17)))))
What I want to do is select multiple values from $C$4:$C$12 based on values in K17:S17 and then sum it. In row K17:S17 there might 1 to 9 positive integers (from 1 to 9), that determine which row to select from C4:C12.
When I use just INDEX($C$4:$C$12,TRANSPOSE(OFFSET(K17,0,0,1,COUNT(K17:S17)))) as an array function it returns the values I want to be sumed properly. but adding sum in frot returns just the first value from this set.
In order to pass an array as INDEX's row_num or col_num parameter, a little coercion is required:
https://excelxor.com/2014/09/05/index-returning-an-array-of-values/
Also, it's better to avoid volatile OFFSET constructions if possible.
=SUM(INDEX($C$4:$C$12,N(IF({1},K17:INDEX(K17:S17,MATCH(9.9E+307,K17:S17))))))
which, incidentally, does not require CSE.
Edit: if the maximum value in the range K17:S17 is 9, we can replace 9.9E+307 with 10:
=SUM(INDEX($C$4:$C$12,N(IF({1},K17:INDEX(K17:S17,MATCH(10,K17:S17))))))
Regards
Related
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.
Is it possible to SUMIF a range where the criteria is not in an array?
For example, I have a list of names in column A and corresponding values in column B. I've created a named range (rngExcludedNames) of those names I want to exclude from the result. I tried the following with no luck:
=SUMIF(Sheet1!A1:A100,COUNTIF(rngExcludedNames,Sheet1!A1:A100)<1,Sheet1!B1:B100)
Any suggestions?
You were close, the SUMPRODUCT() would be a better fit.
Use this formula:
=SUMPRODUCT((COUNTIF(rngExcludedNames,Sheet1!$A$1:$A$100)=0)*(Sheet1!$B$1:$B$100))
SUMPRODUCT() is an array formula. As it iterates through the ranges, in this case it is the two on the Sheet1, it tests each one against the criteria range rngExcludedNames.
So it effectively runs the countIf 100 times, each with different cell in the second criterion. If it returns 0 it is true and returns 1. To which we multiply the value in Column B on the same row as it is iterating with column A. 1 * value = value and 0 * value = 0. As it iterates it sums each result.
My array contains a string in the first row
how can I sum the array from the 2nd row to the Nth/1442th row (as in my example) disregarding the negative signs present in the column?
for example, my code for an array called data2 is:
S = sum(data2(2,15):data2(1442,15));
so sum all of the elements from row 2 to row 1442 in column 15.
This doesn't work but it also does not have anything to deal with the absolute value of whatever row its checking
data is from a .csv:
You should do something like this:
sum(abs(data(2:1442,15)));
The abs function will find the absolute value of each value in the array (i.e. disregard the negative sign). data(2:1442,15) will grab rows 2-1442 of the 15th column, as you wanted.
EDIT: apparently data is a cell array, so you could do the following, I think:
sum(abs([data{2:1442,15}]));
Ok so it looks like you have a constant column so
data2(2,15) = -0.02
and further down
data2(1442,15) = -0.02 %(I would assume)
So when you form:
data2(2,15):data2(1442,15)
this is essential like trying to create an array but of a single value since:
-0.02:-0.02
ans =
-0.0200
which of course gives:
>> sum(-0.02:-0.02)
ans =
-0.0200
What you want should be more like:
sum(data2(2:1442,15))
That way, the index: 2:1442, forms a vector of all the row references for you.
To disregard the negative values:
your answer = sum(abs(data2(2:1442,15)))
EDIT: For a cell array this works:
sum(abs(cell2mat(data2(2:1442,15))))
I am currently using this array formula..
{=LARGE(IF(('Data Input'!$L$3:$L$15000=$B10)*('Data Input'!$H$3:$H$15000>$C10),'Data Input'!$O$3:$O$15000,0),1)}
Where B10 is a text ID, like 658A and L:L is the column with the IDs.
C10 is a date, with H:H being the column with dates.
O:O being the column with the # value that I am retrieving.
This formula works fine with my purposes when used with ctrl,shift,enter
The problem arises when I try to use...
{=IF('Data Input'!$L$3:$L$15000=$B10,1,0)}
It always returns a FALSE result, even though it works correctly in the first formula.
What is different about the second formula that changes the results?
This is very strange to me.
Thanks for any help.
the IF is only comaring the first value of the array that is returned, so only if the first comparison is true, will it return a true value.
Example to illustrate:
formula
Formula:
{=IF(A1:A3=B2,1,0)} will; return 0, unless cell A1 is changed to true. To change the result to have it return true if any of the values are true, you have to resort to a little trickery...
First, use -- to change the True/False values to 1/0, then use SUM to add them together. as IF treats any non-zero result as true, this will result in 1 being returned when any comparison is true.
Working through our example with the new formula {=IF(SUM(--(A1:A3=B2)),1,0)} (still an array formula) we get the following steps in evaluation:
=IF(SUM(--(A1:A3=B2)),1,0)
=IF(SUM(--(A1:A3=2)),1,0)
=IF(SUM(--({1,2,2}=2)),1,0)
=IF(SUM(--({False,True,True})),1,0)
=IF(SUM(0,1,1),1,0)
=IF(2,1,0)
=1
Your second formula is, itself, returning an array. You are only viewing the top left element in that return array - which happens to be FALSE.
Your first formula returns a scalar value; that is the difference.
If you want to sum the '1' values then your second formula could be amended to
{=SUM(IF('Data Input'!$L$3:$L$15000=$B10,1,0))}
which is also a scalar return.
Can anyone tell me if there is a way (in MATLAB) to check whether a certain value is equal to any of the values stored within another array?
The way I intend to use it is to check whether an element index in one matrix is equal to the values stored in another array (where the stored values are the indices of the elements which meet a certain criteria).
So, if the indices of the elements which meet the criteria are stored in the matrix below:
criteriacheck = [3 5 6 8 20];
Going through the main array (called array) and checking if the index matches:
for i = 1:numel(array)
if i == 'Any value stored in criteriacheck'
%# "Do this"
end
end
Does anyone have an idea of how I might go about this?
The excellent answer previously given by #woodchips applies here as well:
Many ways to do this. ismember is the first that comes to mind, since it is a set membership action you wish to take. Thus
X = primes(20);
ismember([15 17],X)
ans =
0 1
Since 15 is not prime, but 17 is, ismember has done its job well here.
Of course, find (or any) will also work. But these are not vectorized in the sense that ismember was. We can test to see if 15 is in the set represented by X, but to test both of those numbers will take a loop, or successive tests.
~isempty(find(X == 15))
~isempty(find(X == 17))
or,
any(X == 15)
any(X == 17)
Finally, I would point out that tests for exact values are dangerous if the numbers may be true floats. Tests against integer values as I have shown are easy. But tests against floating point numbers should usually employ a tolerance.
tol = 10*eps;
any(abs(X - 3.1415926535897932384) <= tol)
you could use the find command
if (~isempty(find(criteriacheck == i)))
% do something
end
Note: Although this answer doesn't address the question in the title, it does address a more fundamental issue with how you are designing your for loop (the solution of which negates having to do what you are asking in the title). ;)
Based on the for loop you've written, your array criteriacheck appears to be a set of indices into array, and for each of these indexed elements you want to do some computation. If this is so, here's an alternative way for you to design your for loop:
for i = criteriacheck
%# Do something with array(i)
end
This will loop over all the values in criteriacheck, setting i to each subsequent value (i.e. 3, 5, 6, 8, and 20 in your example). This is more compact and efficient than looping over each element of array and checking if the index is in criteriacheck.
NOTE: As Jonas points out, you want to make sure criteriacheck is a row vector for the for loop to function properly. You can form any matrix into a row vector by following it with the (:)' syntax, which reshapes it into a column vector and then transposes it into a row vector:
for i = criteriacheck(:)'
...
The original question "Can anyone tell me if there is a way (in MATLAB) to check whether a certain value is equal to any of the values stored within another array?" can be solved without any loop.
Just use the setdiff function.
I think the INTERSECT function is what you are looking for.
C = intersect(A,B) returns the values common to both A and B. The
values of C are in sorted order.
http://www.mathworks.de/de/help/matlab/ref/intersect.html
The question if i == 'Any value stored in criteriacheck can also be answered this way if you consider i a trivial matrix. However, you are proably better off with any(i==criteriacheck)