How to use Calculate with single condition on pivot? - excel

In my pivot table I added a custom column like this:
=CALCULATE(MAX([Column1]),FILTER(table,expr))
I want to add a new condition and after a few tries, this is working as I expected
=IF([Column2]>5, CALCULATE(MAX([Column1]),FILTER(table,expr)) + 10,
CALCULATE(MAX([Column1]),FILTER(table,expr))
)
but this function is quite long (because expr pretty much the condition), I wonder if there is a LET function or some way that can shorten the above function
=CALCULATE( IF (
[Column2]>5,MAX([Column1])+10, MAX([Column1])
)
,FILTER(table,expr))
However this formula doesn't work,
Is there a better solution for this?

Related

Is there an efficient way to do this excel function

In excel I wanted to differentiate the starting time of a trip into 4 'times of day' (Morning, afternoon, evening, Night)
I made this script, the start_time column consists of time (hh:mm:ss)
=IF(
AND([#[start_time]] >= TIME(20,0,0),
[#[start_time]] <= TIME(23,59,59)
),
"Night",
IF(
AND([#[start_time]] >= TIME(0,0,0),
[#[start_time]] < TIME(6,0,0)
),
"Night",
IF(
AND([#[start_time]] >= TIME(6,0,0),
[#[start_time]] < TIME(12,0,0)
),
"Morning",
IF(
AND([#[start_time]] >= TIME(12,0,0),
[#[start_time]] < TIME(16,0,0)
),
"Afternoon",
"Evening"
)
)
)
)
I was wondering if there is any way to improve this function or make it more easy
Thanks in advance!
So, using vlookup() as suggested:
VLOOKUP(E2,$B$4:$C$8,2,1)
The advantage I find is that the times and the text are easily edited.
Firstly, you can significantly simplify your IF statement by removing the ANDs:
=IF([#[Start Time]]-ROUNDDOWN([#[Start Time]],0) < TIME(6,0,0), "Night",
IF([#[Start Time]]-ROUNDDOWN([#[Start Time]],0) < TIME(12,0,0), "Morning",
IF([#[Start Time]]-ROUNDDOWN([#[Start Time]],0) < TIME(16,0,0), "Afternoon",
IF([#[Start Time]]-ROUNDDOWN([#[Start Time]],0) < TIME(20,0,0), "Evening", "Night")
)
)
The -ROUNDDOWN([#[Start Time]],0) here, allows you to enter a time with or without a date. It is not needed if your times do not also have a date attached.
Using a lookup table instead
The benefit of using a lookup table is that you can easily see and change the cut off times in a single place, rather than searching through multiple formulas.
For Lookups, you should NEVER use VLOOKUP. INDEX/MATCH is better in every way. It is more efficient, less fragile, more versatile, and arguably easier to use, once you are familiar with it.
=INDEX(RefTbl[Times Of Day],MATCH([#[Start Time]]-ROUNDDOWN([#[Start Time]],0),RefTbl[End Time],-1))
Recent Excel version has two functions you might use for this: switch() handles the multiple IF() and LET() gives you the opportunity to create a temporary variable inside your formula. (I would have put this in a comment, but two large URLs make this comment too large)

Is it possible to stack values from 4 different columns from two different sheets into one column in third sheet using formula? [duplicate]

I have a FLATTEN LAMBDA function that flattens data in an array. This works well, but I want to integrate another array argument so I can use non-contiguous ranges.
In my example, the range A1:B6 is housed in array and returns the flattened data.
How can I include an array2 argument that accepts D1:D6 as an additional range?
Formula:
FLATTEN =
LAMBDA(array,
LET(
rows,ROWS(array),
columns,COLUMNS(array),
sequence,SEQUENCE(rows*columns),
quotient,QUOTIENT(sequence-1,columns)+1,
mod,MOD(sequence-1,columns)+1,
INDEX(IF(array="","",array),quotient,mod)
)
)
Edit 7/4/22:
ms365 now has introduced a function called VSTACK() and TOCOL() which allows for the the functionality that we were missing from GS's FLATTEN() (and works even smoother)
In your case the formula could become:
=TOCOL(A1:D6,1)
And that small formula (where the 2nd parameter tells the function to ignore empty cells) would replace everything else from below here. If C1:C6 would hold values you don't want to incorporate you can try things like:
=VSTACK(TOCOL(A1:B6),D1:D6)
Previous Answer:
You can't really create a LAMBDA() with an unknown number (beforehand) of arrays to include in flatten. The fact that you have arrays of multiple columns will contribute to the "trickyness". One way to 'flatten' multiple columns in this specific way would be:
Formula in G1:
=LET(X,CHOOSE({1,2,3},A1:A6,B1:B6,D1:D6),Y,COLUMNS(X),Z,SEQUENCE(COUNTA(X)),INDEX(X,CEILING(Z/Y,1),MOD(Z-1,Y)+1))
EDIT: As per your comment, you can extend this as such:
=LET(X,CHOOSE({1,2,3},IF(A1:A6="","",A1:A6),IF(B1:B6="","",B1:B6),IF(D1:D6="","",D1:D6)),Y,COLUMNS(X),Z,SEQUENCE(ROWS(X)*Y),FLAT,INDEX(X,CEILING(Z/Y,1),MOD(Z-1,Y)+1),FILTER(FLAT,FLAT<>""))
It's a cheat, but:
FLATTEN =
LAMBDA(array,
LET(
rows,ROWS(array),
columns,COLUMNS(array),
sequence,SEQUENCE(rows*columns),
quotient,QUOTIENT(sequence-1,columns)+1,
mod,MOD(sequence-1,columns)+1,
unpiv, INDEX(array,quotient,mod),
FILTER(unpiv, unpiv<>"")
)
)
Where your array has been extended to A1:D6 as the input.
I think JvdV's answer will be the best depending on the input format
you want, but I had already written this out, so here goes...
You could do:
=LET( array1, A1:B6, array2, D1:D6,
rows1,ROWS(array1), rows2,ROWS(array2),
columns1,COLUMNS(array1), columns2,COLUMNS(array2),
rows, MIN(rows1, rows2),
columns, columns1 + columns2,
sequence,SEQUENCE(rows*columns),
quotient,QUOTIENT(sequence-1,columns)+1,
mod,MOD(sequence-1,columns)+1,
IFERROR(INDEX( IF( ISBLANK(array1),"",array1),quotient,mod),
INDEX(IF( ISBLANK(array2),"",array2),quotient,MOD(sequence-1,columns2)+1) )
)
It will take multi-column/row inputs to both arrays.
Starting from the article here and updating based upon observations about empty values in the arrays and allowing varying sized arrays we can get two formulae which you should be able to translate to Named LAMBDA functions for 'stacking' and 'shelving' arrays.
Stack Arrays
=LET(rngA, A1:C5, rngB, A9:D11,
rowsA, ROWS(rngA), rowsB, ROWS(rngB),
NumCols, MAX(COLUMNS(rngA), COLUMNS(rngB)),
SeqRow, SEQUENCE(rowsA + rowsB), SeqCol, SEQUENCE(1, NumCols),
Result, IF(SeqRow <= rowsA, INDEX(IF(rngA="","",rngA), SeqRow, SeqCol),
INDEX(IF(rngB="","",rngB), SeqRow-rowsA, SeqCol)),
arr, IFERROR(Result,""), arr)
Shelve Arrays
=LET(rngA, A1:C5, rngB, B8:D12,
colsA, COLUMNS(rngA), colsB, COLUMNS(rngB),
NumRows, MAX(ROWS(rngA), ROWS(rngB)),
SeqRow, SEQUENCE(NumRows), SeqCol, SEQUENCE(1, colsA + colsB),
Result, IF(SeqCol <= colsA, INDEX(IF(rngA="","",rngA), SeqRow, SeqCol),
INDEX(IF(rngB="","",rngB), SeqRow, SeqCol-colsA ) ),
arr, IFERROR(Result,""), arr)
Once you have a contiguous array, you can apply the formula you already have:
Updated to use a spill range for ease of testing...
=LET(data, A1#,
rows, ROWS(data), cols, COLUMNS(data),
seq, SEQUENCE(rows*cols,,0),
list, INDEX(IF(data="", "", data), QUOTIENT(seq, cols)+1, MOD(seq, cols)+1),
FILTER(list, LEN(list)>0))
This approach is really geared towards the named LAMBDA functions because otherwise you will end up with monstrous formulae and the other approaches may well be better in that case.

Is there a pandas function that can create a dataframe of the mean, median, and mode of selected columns?

My attempt:
# Compute the mean, median and variance for the variables sph, acous and dur. Compare their level of variability.
sad_mean = dat_songs[['spch', 'acous', 'dur']].mean()
sad_mode = dat_songs[['spch', 'acous', 'dur']].mode()
sad_median = dat_songs[['spch', 'acous', 'dur']].median()
sad_mmm = pd.DataFrame({'mean':sad_mean, 'median':sad_median, 'mode':sad_mode})
sad_mmm
Which outputs this
First of all, the median column is not right at all and want to know how to fix that too.
Secondly, I feel like I have seen some quicker or shorter way to do this with a simple function with pandas.
My data head for reference
Simply try, dat_songs.describe(). Descriptive Statistics will be present for all the numerical columns.
For selected columns.
dat_songs[['spch', 'acous', 'dur']].describe()

Query a range in an Excel table linked to PowerApps Text Search box

First time asking a question here. As well as being pretty new to PowerApps as well.
I am trying to use two text input boxes for the user to define the min & max of their number range. basically i want the code to return all results that fall in the user defined range.
User inputs are:
SearchText.Text
MinSearch.Text and
MaxSearch.Text
PDFData is the table, and
RMANumber is the column that i want the Min & Max to search and return all within the user defined range. as of now, all i can get this to return are exact results, which just won't work for my situation. In my way of thinking, i want to add WHERE after the RAWidth and give greater or lesser arguments, but this isn't working for me. My full code is below, and any help is appreciated.
If(SearchText.Text="" && MinSearch.Text="" && MaxSearch.Text="", PDFData, Filter(PDFData,SearchText.Text in PDFAuthor|| SearchText.Text in PDFName|| SearchText.Text in RMANumber|| MinSearch.Text in RAWidth))
You can use the following expression for your query:
Filter(
PDFData,
SearchText.Text in PDFAuthor || SearchText.Text in PDFName,
Coalesce(Value(MinSearch.Text), -1) <= RAWidth,
Coalesce(Value(MaxSearch.Text), 1000000000) >= RAWidth)
If the SearchText is empty, then the conditions SearchText.Text in PDFAuthor and SearchText.Text in PDFName will both be true anyway, so there's no need for the If at that point.
For the other conditions, we can use the functions Value / Coalesce to convert the text input to a number; if the user didn't enter anything (or entered an invalid number), then the function Value will return a blank value, and the Coalesce function will use the next value. I'm using here -1 for the minumum value and 1000000000 for the maximum - if the possible range of values in your RAWidth column is between those numbers then you're fine.

IF function for specific text strings

I am trying to write a formula that takes a word and process it through a IF function in excel, The Values are list in the formula. My issue right now is the fact that I have Large, X-Large and 1X-Large text. The X-Large and 1X-Large are unique strings and need the IF function to be able to differentiate the two.
Here is what i have so far.
=if(or(isnumber(search("Small",af2)),ISNUMBER(SEARCH("Medium",AF2)),ISNUMBER(SEARCH("Large",AF2)),,ISNUMBER(SEARCH("X-Large",AF2))),"Small",or(isnumber(search("1X-Large",af2)),isnumber(search("2X-Large",af2)),isnumber(search("3X-Large",af2)),isnumber(search("4X-Large",af2))),"1X-Large")
I cant understand why it's showing an error and only displays small when it works.
All help is appreciated
Your current formula shouldn't work, it should be giving you an error about having too many arguments. A breakdown of your function:
=if(
or(isnumber(search("Small",af2)),ISNUMBER(SEARCH("Medium",AF2)),ISNUMBER(SEARCH("Large",AF2)),,ISNUMBER(SEARCH("X-Large",AF2))),
"Small",
or(isnumber(search("1X-Large",af2)),isnumber(search("2X-Large",af2)),isnumber(search("3X-Large",af2)),isnumber(search("4X-Large",af2))),
"1X-Large"
)
You cannot use 4 parameters in an IF. You need to have a maximum of 3. Maybe what you meant was:
=if(
or(isnumber(search("Small",af2)),ISNUMBER(SEARCH("Medium",AF2)),ISNUMBER(SEARCH("Large",AF2)),,ISNUMBER(SEARCH("X-Large",AF2))),
"Small",
IF(
or(isnumber(search("1X-Large",af2)),isnumber(search("2X-Large",af2)),isnumber(search("3X-Large",af2)),isnumber(search("4X-Large",af2))),
"1X-Large"
)
)
But that doesn't solve your issue about the X-Large part. To cater for that, you can check whether the X-Large series exist first, then the others.
=IF(
OR(ISNUMBER(SEARCH("1X-Large",AF2)),ISNUMBER(SEARCH("2X-Large",AF2)),ISNUMBER(SEARCH("3X-Large",AF2)),ISNUMBER(SEARCH("4X-Large",AF2))),
"1X-Large",
IF(
OR(ISNUMBER(SEARCH("Small",AF2)),ISNUMBER(SEARCH("Medium",AF2)),ISNUMBER(SEARCH("Large",AF2)),ISNUMBER(SEARCH("X-Large",AF2))),
"Small"
)
)
Although you can make it shorter with this:
=IF(
OR(ISNUMBER(SEARCH({"1X-Large","2X-Large","3X-Large","4X-Large"},AF2))),
"1X-Large",
IF(
OR(ISNUMBER(SEARCH({"Small","Medium","Large","X-Large"},AF2))),
"Small"
)
)
In one line...
=IF(OR(ISNUMBER(SEARCH({"1X-Large","2X-Large","3X-Large","4X-Large"},AF2))),"1X-Large",IF(OR(ISNUMBER(SEARCH({"Small","Medium","Large","X-Large"},AF2))),"Small"))

Resources