Home > Net >  STDEV ARRAYFORMULA in Google Sheets
STDEV ARRAYFORMULA in Google Sheets

Time:08-09

since STDEV is not supported under ARRAYFORMULA there is either draggable solution:

enter image description here

or hardcoded solution:

enter image description here

but neither of them is dynamically scalable so is there any workaround?

from a quick google search, it looks like no one dared to dream of such lengths

data sample:

b   5
a   1
a   2
b   5
a   1

desired result:

a   0.5773502692
b   0

CodePudding user response:

the math says that standard deviation can be achieved as:

enter image description here

if we substitute for formulae we get:

enter image description here

knowing the above we can easily convert it into a multidimensional array... let's start with the first query where we pivot labels:

enter image description here

removing labels:

enter image description here

calculating the average:

enter image description here

removing labels:

enter image description here

for subtraction, we need to exclude empty cells so we use IF:

enter image description here

and raise it on the 2nd power:

enter image description here

now we can sum it up per column with MMULT or QUERY again:

enter image description here

to make it more dynamic we can construct query selection with SEQUENCE:

enter image description here

next is division by count:

enter image description here

then square root:

enter image description here

now we just add back labels:

enter image description here

and transpose it:

=ARRAYFORMULA(TRANSPOSE({INDEX(QUERY({A:B}, 
 "select max(Col2) where Col1 is not null group by Col2 pivot Col1"), 1); 
 (QUERY(QUERY(IF(QUERY(QUERY({A:B, ROW(A:A)}, 
 "select max(Col2) where Col2 is not null group by Col3 pivot Col1"), "offset 1", )="",,
 (QUERY(QUERY({A:B, ROW(A:A)}, 
 "select max(Col2) where Col2 is not null group by Col3 pivot Col1"), "offset 1", )-
 QUERY(QUERY({A:B, ROW(A:A)/0}, 
 "select avg(Col2) where Col2 is not null group by Col3 pivot Col1"), "offset 1", ))^2), 
 "select "&TEXTJOIN(",", 1, "sum(Col"&SEQUENCE(COUNTUNIQUE(A:A))&")")), "offset 1", )/
 (INDEX(TRANSPOSE(QUERY({A:B}, 
 "select Col1,count(Col1) where Col1 is not null group by Col1 label count(Col1)''")), 2)-1))^(1/2)}))

enter image description here



it works, but we can do better... simple IF statement will do:

enter image description here

but to make it fast and smart we need some tweaks to counter empty cells and unsorted dataset:

enter image description here

we add errors:

enter image description here

subtract the average:

enter image description here

raise on the 2nd power:

enter image description here

remove errors with IFNA and sum it:

enter image description here

divide by count-1:

enter image description here

take a square root:

enter image description here

transpose it and add back labels:

=INDEX(IFERROR({SORT(UNIQUE(FILTER(A:A, A:A<>""))), FLATTEN(( 
 INDEX(QUERY(IFNA((IF(FILTER(A:A, A:A<>"")=TRANSPOSE(SORT(UNIQUE(
 FILTER(A:A, A:A<>"")))), FILTER(B:B, B:B<>""), NA())-INDEX(QUERY({A:B, ROW(A:A)/0}, 
 "select avg(Col2) where Col2 is not null group by Col3 pivot Col1"), 2))^2), 
 "select "&TEXTJOIN(",", 1, "sum(Col"&SEQUENCE(COUNTUNIQUE(A:A))&")")), 2)/TRANSPOSE(QUERY({A:B}, 
 "select count(Col1) where Col1 is not null group by Col1 label count(Col1)''")-1))^(1/2))}))

enter image description here

CodePudding user response:

Outstanding solution and thanks for the clear walk-through, @player0!

  • Related