Related
This is probably one of those questions with a very simple solution.
Due to security concerns, I can't go into much detail as to the specifics of my data, but to surmise:
I have three groups of people, divided up into three groups - "red", "blue", and "green". Each person gets a score, and its all contained in a table. I need a formula that returns the name of the highest scoring member of each group (as opposed to the highest score overall), and I can't add any helper columns.
Thank you in advance! :)
I've tried to use XLOOKUP to look up the MAX Values of each group, but the result returns the first person who matches that score - who might be in a different group. I've also tried to use Index/Match to match the highest MAXIFS score which worked until I used in a table and then it fell apart.
Try FILTER() with few other functions.
=INDEX(SORT(FILTER($A$3:$C$13,$B$3:$B$13=E5),3,-1),1,{1,3})
To get all by single formula and spill result dynamically, try-
=HSTACK(UNIQUE(B3:B13),
BYROW(UNIQUE(B3:B13),LAMBDA(x,INDEX(SORT(FILTER(A3:C13,B3:B13=x),3,-1),1,1))),
BYROW(UNIQUE(B3:B13),LAMBDA(x,INDEX(SORT(FILTER(A3:C13,B3:B13=x),3,-1),1,3))))
You can use Pivot Tables to get the output you want:
Just take fields Group and Name into rows section and Score into values section. Then apply a filter values on field Name group and choose last option TOP 10 and set it up to show only top 1:
[Filter data in a PivotTable](https://support.microsoft.com/en-us/office/filter-data-in-a-pivottable-cc1ed287-3a97-4e95-b377-ddfafe79fa8f)
Why using Pivot Tables if there are formulas? Because in case there is any tie, the Pivot Table will show up those values and formulas won't!
Just as example, let's say Collin got also 46 Score like Arturo. Both of them are the highest value so both of them are the 1st ones. Pivot Table will show this:
Easy to update and make less errors.
MaxIFS() to the rescue:
This is the formula:
=MAXIFS(B1:B8,A1:A8,"Red")
This is how to use it:
Pivot Table + Power Pivot:
Since you are working with an actual table, here is a fun alternative using a Pivot Table with a Power Pivot measure written in Data Analysis Expressions (DAX):
Select any cell in your table;
On the 'Insert' tab, click 'Pivot Table' and tick the 'Add this data to the Data Model' box before clicking 'OK';
Now go to the 'Power Pivot' tab and choose to add a new measure in the 'Calculations' group;
Give it any reasonable 'Measure name' and in the formula section use:
=MAXX(TOPN(1,VALUES(Table1[Name]),CALCULATE(MAX(Table1[Score])),DESC),[Name])
Now hit 'OK';
Select the Pivot Table you created and make sure that you have the 'Group' field selected as 'Rows';
Now we have it, a calculated field using our own measure showing the top scorer per Group:
When new data is added to the model (or changed), you'd need to refresh the Pivot Table >> 'Table Design' >> 'Refresh All'.
Formula:
If a formula is a must, then maybe try:
Formula in E7:
=LET(x,UNIQUE(Table1[Group]),HSTACK(x,MAP(x,LAMBDA(x,#SORT(FILTER(Table1,Table2[Group]=x),3,-1)))))
PowerQuery:
A 3rd option could be to run a quick analyses in PowerQuery:
Select any cell in your table and on the 'Data' tab, click 'From Table/Range' in the 'Get & Transform Data' group;
Select the 2nd column, and choose the 'Group By' option on the 'Transform' tab;
Make sure that you make the following aggregations in the 'Advanced' tab:
Now, on the 'Add Column' tab, choose the 'Custom Column' in the 'General' group;
Pick a name for your new column, I choose 'Best' and add the following formula:
= Table.Max([Helper2], "Score")
If done correctly, your data will now look like:
Now, on the 'Add Column
Click the 'Expand' button (top right in 'Best.Name') and just select only 'Name';
Delete the two helpers, and you'll be good to go and close & load the query back to Excel:
Here is the M-code for completion's sake:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Name", type text}, {"Group", type text}, {"Score", Int64.Type}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"Group"}, {{"Helper1", each List.Max([Score]), type nullable number}, {"Helper2", each _, type table [Name=nullable text, Group=nullable text, Score=nullable number]}}),
#"Added Custom" = Table.AddColumn(#"Grouped Rows", "Best", each Table.Max([Helper2], "Score")),
#"Expanded Best" = Table.ExpandRecordColumn(#"Added Custom", "Best", {"Name"}, {"Best.Name"}),
#"Removed Columns" = Table.RemoveColumns(#"Expanded Best",{"Helper1", "Helper2"})
in
#"Removed Columns"
Power-Query-Result-Table
Pivot-Table on Power-Query-Result-Table
I am getting the list in the first screenshot as a result from the Power-Query-Editor.
Now I want to apply a Report Filter to it. Therfore, I put the data into a Pivot-Table.
In general this solution is working but I am wondering if it is possible to have the Report Fitler directly in the Power-Query-Result-Table to avoid an additional Pivot-Table?
You can filter for crew directly in the PowerQuery using the drop down atop the crew column like below image. In this image I filter for Crew=J
That generates code as follows:
#"Filtered Rows" = Table.SelectRows(#"Changed Type", each [Crew] = "J")
If you put J into a a cell on the excel sheet and gave that cell a range name like CrewName, you could reference that range name in the powerquery and filter dynamically
#"Filtered Rows"= Table.SelectRows(#"Changed Type", each [Crew] = Excel.CurrentWorkbook(){[Name="CrewName"]}[Content]{0}[Column1])
I'm at my wits end. What formula should I even go for? Can I achieve what I'm trying to do in Google Sheets?
I have attached a picture of a mockup what I'm trying to do.
Basically I have 2 tables. Let us call them "Calendar" - TABLE A and "Schedule" TABLE B.
TABLE A - I mark manually an event and a name or names behind it.
TABLE B - Is the table I'm trying to create a formula for. In the picture colored green is where the formula bit should be. Basically trying to search TABLE A and match the Date (19 July) with the name (Mary)
So in text the formula matches TABLE A information of 19 July and every cell with Mary and displays it in TABLE B, under the fields Mary and 19 July displays what TABLE A had going for him.
Cool if I could simply trim the end result and remove other names, so if there was "Mary and Richard", it would know to remove those names from the fields.
So basically display every cell with "Mary" in TABLE A, and display it in TABLE B under one cell.
Here's an option with a helper sheet.
Let's say your data is on a sheet called Data, range Data!A1:AB21:
Create a helper sheet called Formula:
Cell B2 gets the headers from the Data sheet:
={Data!A1:AB1}
Cells A2:A5 have the fixed names, Mark, John, Richard, Tom.
This formula goes in EVERY cell within the range B2:AC5 (drag down and drag across):
=arrayformula(iferror(textjoin(",",1,trim(regexreplace(filter(Data!A:A,regexmatch(Data!A:A,$A2)),textjoin("|",1,$A$2:$A$5),))),))
A final Sheet called 'Results' has this in cell A1:
=transpose(Formula!A:AC)
It's not as elegant as having an arrayformula in a single cell on the Formula sheet, but it does work once you've set the data range and dragged the formula down and across.
You can obtain your results using Power Query provided that:
There is a reproducible method of obtaining the Names
In your example, each name is a single word, and they all occur together at the end of an activity substring
Multi-name words will require a different algorithm to extract.
To use Power Query (available in Windows Excel 2010+ and Office 365)
Select some cell in your Data Table
Data => Get&Transform => from Table/Range
When the PQ Editor opens: Home => Advanced Editor
Make note of the Table Name in Line 2
Paste the M Code below in place of what you see
Change the Table name in line 2 back to what was generated originally.
Read the comments and explore the Applied Steps to understand the algorithm
M Code
let
Source = Excel.CurrentWorkbook(){[Name="TableA"]}[Content],
//need to hard code list of names
names = {"Mary","John","Richard","Tom"},
//Type all as text
#"Changed Type" = Table.TransformColumnTypes(Source,
List.Transform(Table.ColumnNames(Source), each {_, Text.Type})),
//Unpivot to => a two column list
#"Unpivoted Columns" = Table.UnpivotOtherColumns(#"Changed Type", {}, "Dates", "Value"),
//Extract the names
#"Added Custom" = Table.AddColumn(#"Unpivoted Columns", "Names", each List.Intersect({Text.Split([Value]," "),names})),
//Extract the Activities
#"Added Custom1" = Table.AddColumn(#"Added Custom", "Activity", each Text.Start([Value],Text.PositionOf([Value],[Names]{0})-1)),
//Remove unneeded column
#"Removed Columns" = Table.RemoveColumns(#"Added Custom1",{"Value"}),
//Expand the names to => single row for each name/date
#"Expanded Names" = Table.ExpandListColumn(#"Removed Columns", "Names"),
//Group by Date and Name
// Aggregate the activites
grouped = Table.Group(#"Expanded Names",{"Dates","Names"},{
{"Activities", each Text.Combine([Activity],", "), type text}
}),
#"Pivoted Column" = Table.Pivot(grouped, List.Distinct(grouped[Names]), "Names", "Activities"),
//reArrange columns to desired order
#"Reordered Columns" = Table.ReorderColumns(#"Pivoted Column",List.Combine({{"Dates"}, names}))
in
#"Reordered Columns"
Table A
Table B
I have 15ish data sources that contain a date and some values. But the dates can be different from one sheet to another.
Sheet 1
Date
Infected
2020-03-28
10
2020-03-29
20
...
Sheet 2
Date
Infected
2020-04-15
5
2020-04-16
7
...
My goal is to produce a combined line graph containing all the sheets, but some tables have more data than others with the date series.
I can think of only one option to make them all the same size and cover all date values: Merge queries in Power Query (essentially many left joins to bring all sheets together and combine all the dates).
Is there another option I'm missing to combine these tables? Something at the graph level maybe so they can all refer to their own date series?
Tables that are structured like this and stored in different worksheets can be merged using the pivot function. Here are 2 scenarios based on the assumption each table is saved on a separate worksheet within a single Excel workbook:
1. Each table is saved as an Excel Table. The Tables are combined into a single table using Power Query and the resulting table is then loaded into a new worksheet.
2. The tables are not saved as Excel Tables, and doing this manually or figuring out how to execute this process with a VBA script seems like a lot of work. In this case, the tables can be more easily combined by creating a new Excel workbook and then connecting to the file containing the tables by using Power Query.
Here is an example for each scenario. The dataset consists of 3 tables each containing 10 rows where the dates between tables overlap a bit.
Scenario 1 - Data stored in Excel Tables
Here is what the sample data looks like in the first worksheet containing an Excel Table named Source1:
With all tables saved as Excel Tables and named following the same convention, it is time to open the Power Query Editor and complete the following steps:
Create a blank query and type = Excel.CurrentWorkbook() in the formula bar to list all the named objects contained in the workbook.
Filter the Name column to keep only rows with names starting with Source to avoid including the table combining all the data into this query once it is completed and refreshed.
Click on the expand button of the Date column, uncheck Use original column name as prefix and click OK.
Change the Date column data type to date.
Pivot the Name column with the Infected column as the Values Column and with Don't Aggregate selected under Advanced Options.
Now the data is merged appropriately and can be loaded in a new worksheet to create the line graph:
Here is the M code:
let
Source = Excel.CurrentWorkbook(),
#"Filtered Rows" = Table.SelectRows(Source, each Text.StartsWith([Name], "Source")),
#"Expanded Content" = Table.ExpandTableColumn(#"Filtered Rows", "Content", {"Date", "Infected"}, {"Date", "Infected"}),
#"Changed Type" = Table.TransformColumnTypes(#"Expanded Content",{{"Date", type date}}),
#"Pivoted Column" = Table.Pivot(#"Changed Type", List.Distinct(#"Changed Type"[Name]), "Name", "Infected")
in
#"Pivoted Column"
Scenario 2 - Data not stored in Excel Tables
In this scenario, the data is stored in an external Excel workbook datasources.xlsx. Here is what the sample data looks like in the first worksheet:
In a separate Excel workbook, open the Power Query Editor and complete the following steps:
Create a blank query and type the following line in the formula bar using the appropriate file path: = Excel.Workbook(File.Contents("C:\FilePath\datasources.xlsx"))
Remove all columns except Name and Data.
Click on the expand button of the Data column, uncheck Use original column name as prefix and click OK.
Promote the first row to column headers.
Edit the data types for the Date and Infected columns.
Select the Date column and remove rows containing errors.
Pivot the Sheet1 column with the Infected column as the Values Column and with Don't Aggregate selected under Advanced Options.
Now the data is merged appropriately and can be loaded in a new worksheet to create the line graph, yielding the same result as in Scenario 1 except for the column headers and legend labels:
Here is the M code:
let
Source = Excel.Workbook(File.Contents("C:\FilePath\datasources.xlsx")),
#"Removed Columns" = Table.RemoveColumns(Source,{"Item", "Kind", "Hidden"}),
#"Expanded Data" = Table.ExpandTableColumn(#"Removed Columns", "Data", {"Column1", "Column2"}, {"Column1", "Column2"}),
#"Promoted Headers" = Table.PromoteHeaders(#"Expanded Data", [PromoteAllScalars=true]),
#"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"Sheet1", type text}, {"Date", type date}, {"Infected", Int64.Type}}),
#"Removed Errors" = Table.RemoveRowsWithErrors(#"Changed Type", {"Date"}),
#"Pivoted Column" = Table.Pivot(#"Removed Errors", List.Distinct(#"Removed Errors"[Sheet1]), "Sheet1", "Infected")
in
#"Pivoted Column"
I would like to create two columns from a table.
The correct solution will be this (this will be to 2 separate columns):
From this table:
The table is much longer than this, this is an example.
Can you help me to solve this?
Thanks,
Gergo
To load your existing data into PQ, it needs to be a table. To make this easy, I would convert it to a table and have "My table has headers" unchecked. Then put some labels on your identifier rows so we can easily convert them. It looked like this after I did it.
Then load your table into PQ with the "From Table" option. It will probably try to set types and promote headers by default, which isn't helpful, so delete those steps. It should look like this.
To be able to map your multiple row headers, we'll need to do some pivot transforms. Make a reference to the table we just imported.
Keep the first 3 rows, select the first column and "Unpivot Other Columns". Then select the first column again and "Pivot Columns". Select the "Value" column as your "Values Column" and under the "Advanced options" select "Don't Aggregate".
After this pivot you'll now have a table that maps all of your columns to their header rows. I converted the column with the numbers to text since we'll be appending it as text later on. The result table looks like this:
The full code for this query was:
let
Source = Table1,
#"Kept First Rows" = Table.FirstN(Source,3),
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Kept First Rows", {"Column1"}, "Attribute", "Value"),
#"Pivoted Column" = Table.Pivot(#"Unpivoted Other Columns", List.Distinct(#"Unpivoted Other Columns"[Column1]), "Column1", "Value"),
#"Changed Type" = Table.TransformColumnTypes(#"Pivoted Column",{{"Region", type text}})
in
#"Changed Type"
Then go back and make another reference to your imported table. This time remove the top 3 rows, select the first column and Unpivot Other Columns. You'll get a list of your dates with all the other columns of data unpivoted next to them. Now you can Merge Queries by matching the Attribute columns from this table and the table where you mapped out your header rows.
Expand the merged data and now you have your header rows mapped to every line of data in your table. You can add a custom column that creates the unique ID column you wanted, then remove and move around the columns to get the result data you want. The custom column code looked like this for me:
[Country Code]&"_"&DateTime.ToText([Column1], "MM/dd/yyyy")&"_"&[Region]
And this was the result table:
The full M code for this part was:
let
Source = Table1,
#"Removed Top Rows" = Table.Skip(Source,3),
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Removed Top Rows", {"Column1"}, "Attribute", "Value"),
#"Merged Queries" = Table.NestedJoin(#"Unpivoted Other Columns",{"Attribute"},RowIDs,{"Attribute"},"RowIDs",JoinKind.LeftOuter),
#"Expanded RowIDs" = Table.ExpandTableColumn(#"Merged Queries", "RowIDs", {"Country Code", "Country", "Region"}, {"Country Code", "Country", "Region"}),
#"Added Custom" = Table.AddColumn(#"Expanded RowIDs", "ID", each [Country Code]&"_"&DateTime.ToText([Column1], "MM/dd/yyyy")&"_"&[Region]),
#"Removed Other Columns" = Table.SelectColumns(#"Added Custom",{"Value", "ID"}),
#"Reordered Columns" = Table.ReorderColumns(#"Removed Other Columns",{"ID", "Value"})
in
#"Reordered Columns"
You can use the unpivot function of Power Query to achieve this. Below instruction might at first seem long and difficult but it takes no more than one minute when you get the logic.
At first, arrange your headers into just one row. I think the country name can be omitted. So create a new header row as Row:4 and concatenate country code and integer with a such formula in B4 and copy right:
=B1&B3
Now copy 4th row and paste onto the same row as Values Only. The you may delete rows 1-3 and left with just one row as the header. Now you should have AT32 in B1, AT38 in C1 etc.
Now get your data into Power Query. When a non-blank cell is selected in your table, go to Data Ribbon, press From Table/Range button. Now your data is in Power Query.
Select columns with numeric values in it, not the dates and press Transform / Unpivot Columns / Unpivot Columns button. This will get your data into the requested format.
You may now get your sorted & pivoted data back to Excel using Home / Close & Load button.
To get all country and date information into cell, create a new column and use a formula like below:
= LEFT(B2,2) & "_" & TEXT(A2, "dd/mm/yyyy") & "_" & RIGHT(B2, 2)