Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
tross4012
Helper I
Helper I

How to reference an index from another table in a function

Hey everyone,

 

Just started using Power BI last week and am running into a roadblock. I have a function, Clean/Format, that needs to be applied to every table in the "Record" column. I want to reference the "Index" value in my function so that when I Invoke a Custom Function it applies to each row respectively rather than only applying to the row with an "Index" value of 1. 

tross4012_0-1689793830517.png

Below is the DAX script. Criticisms are appreciated as I am aware that this script is likely inefficient.

tross4012_1-1689793848358.png

 

Thanks all.

1 ACCEPTED SOLUTION

 

let
    expand = (tbl) => Table.SplitColumn(Table.TransformColumns(Table.FromList(tbl, Splitter.SplitByNothing(), null, null, ExtraValues.Error), {"Column1", each Text.Combine(List.ReplaceValue(_,null,"",Replacer.ReplaceValue), "|"), type text}), "Column1", Splitter.SplitTextByDelimiter("|", QuoteStyle.Csv),{"LocationFacilty","LocationStatus","LocationCity","LocationState","LocationZip","LocationCountry","LocationContactName","LocationContactEmail","LocationContactPhone"}),
    Source = Excel.Workbook(File.Contents("C:\Users\xxx\Downloads\10examples.xlsx"), null, true),
    Sheet1_Sheet = Source{[Item="Sheet1",Kind="Sheet"]}[Data],
    #"Added Custom" = Table.AddColumn(Sheet1_Sheet, "URL data", each Json.Document( Web.Contents("https://classic.clinicaltrials.gov/api/query/study_fields?expr=AREA[NCTId]" & [Column1] & " &fields=NCTId,BriefTitle,LocationFacility,LocationStatus,LocationCity,LocationState,LocationZip,LocationCountry,LocationContactName,LocationContactEmail,LocationContactPhone&fmt=json"))[StudyFieldsResponse][StudyFields]{0}),
    #"Expanded URL data" = Table.ExpandRecordColumn(#"Added Custom", "URL data", {"Rank", "NCTId", "BriefTitle", "LocationFacility", "LocationStatus", "LocationCity", "LocationState", "LocationZip", "LocationCountry", "LocationContactName", "LocationContactEMail", "LocationContactPhone"}),
    #"Added Custom1" = Table.AddColumn(#"Expanded URL data", "Custom", each try expand(List.Zip({[LocationFacility],[LocationStatus],[LocationCity],[LocationState],[LocationZip],[LocationCountry],[LocationContactName],[LocationContactEMail],[LocationContactPhone]})) otherwise #table({"LocationFacilty", "LocationStatus", "LocationCity", "LocationState", "LocationZip", "LocationCountry", "LocationContactName", "LocationContactEmail", "LocationContactPhone"},{{"", "", "", "", "", "", "", "", ""}})),
    #"Replaced Value" = Table.ReplaceValue(#"Added Custom1",each [BriefTitle],each List.First([BriefTitle]),Replacer.ReplaceValue,{"BriefTitle"}),
    #"Removed Other Columns" = Table.SelectColumns(#"Replaced Value",{"Column1", "BriefTitle", "Custom"}),
    #"Expanded Custom" = Table.ExpandTableColumn(#"Removed Other Columns", "Custom", {"LocationFacilty", "LocationStatus", "LocationCity", "LocationState", "LocationZip", "LocationCountry", "LocationContactName", "LocationContactEmail", "LocationContactPhone"})
in
    #"Expanded Custom"

 

This works for the test IDs.  

Note 1: because of the empty lists I had to remove nulls with empty strings

Note 2: The second to last ID has no extra data at all, so I had to introduce a dummy stand-in table

View solution in original post

19 REPLIES 19
tross4012
Helper I
Helper I

Sample Data/Link to the file:

Here is the link to the file, which includes the sample data. The main items of reference here are the "New Source" table and the "Clean/Format" function:

 

Expected Results:

I click on the "Table" in the "Clean/Format" column for row 1.

tross4012_0-1689953113913.png

This results are correct:

tross4012_1-1689953136950.png

 

Then I click on the "Table" in the "Clean/Format" column for row 2:

tross4012_2-1689953298829.png

This results are incorrect:

tross4012_3-1689953356238.png

 

The only way to fix this, is if I manually change the index in my M script from:

 

Record = #"Added Index"{0}[Record],

 

 to:

 

Record = #"Added Index"{1}[Record],

 

 

I expect each "Table" in the "Clean/Format" column to display information respective to the value in the NCTId column. See the following example.

 

I click on the "Table" in the "Clean/Format" column for row 7:

tross4012_4-1689953675975.png

 

Without MANUALLY changing the M script to:

 

 Record = #"Added Index"{6}[Record],

 

 

The following table should display:

tross4012_5-1689953892030.png

 

Please let me know if there is any other information that you need to further understand my question/problem!

can you please provide the "10examples.xlsx" file as well?

Here is the "10examples.xlsx" file:

https://docs.google.com/spreadsheets/d/1DjJcokSpsF75NUvm7ydoun8j14tmv1yb/edit?usp=sharing&ouid=11178...

 

Thanks for taking the time to help me with this!

Thank you.

 

You seem to be applying a lot of nested (and redundant) transforms, for example 

 

 

#"Added Custom" = Table.AddColumn(#"Changed Type", "Custom", each Table.AddColumn(#"Changed Type", "Custom", each Table.AddColumn(#"Changed Type", "Add Url", each ...

 

 

 

That's probably making your life harder than necessary.  Can you describe what you are ultimately trying to achieve?  Fetch the records for your example IDs from the website and put them into a table? Does their API also support other formats besides XML? I see you are reading the XML as CSV and then are trying to interpret that.  Impressive but not really how you want to do that. There is a native XML parser in Power Query.

 

Something like this

let
    Source = Excel.Workbook(File.Contents("C:\Users\xxx\Downloads\10examples.xlsx"), null, true),
    Sheet1_Sheet = Source{[Item="Sheet1",Kind="Sheet"]}[Data],
    #"Changed Type" = Table.TransformColumnTypes(Sheet1_Sheet,{{"Column1", type text}}),
    #"Added Custom" = Table.AddColumn(#"Changed Type", "URL data", each Xml.Document( Web.Contents("https://classic.clinicaltrials.gov/api/query/full_studies?expr=AREA[NCTId]" & [Column1] & "&fmt=xml"))[Value]{0})
in
    #"Added Custom"

 

 

 

 

Yeah, this is one of my first times using Power BI so theres a lot of optimization to be done. Their API only supports XML and JSON formats so the aforementioned transforms are just trying to parse the data and assign them to the correct columns/rows. 

 

I fetch the information using the NCTId and then put it into a table, which looks like the screenshot below. 

tross4012_0-1690223074016.png

Ultimately, I want to automate this so it makes the call for each NCTId and formats it. The final NCTId list will have 17,000 records so I cannot do this manually!

 

Thanks again.

 

This is how the output looks like 

classic.clinicaltrials.gov/api/query/full_studies?expr=AREA[NCTId]NCT02579226&fmt=xml

 

XML is hierarchical, so you will have to indicate the path to each of the data points you want to extract.  There will be some friction as Power BI expects a table whereas XML is hierarchical. Oh wait, I mentioned that already...

So you're using the full study call, which is used in the table called "Sheet1". You can disregard that. 

 

Look at the table called "Original Source". This utilizes the study fields call, which looks like this:

 

https://classic.clinicaltrials.gov/api/query/study_fields?expr=AREA[NCTId]NCT02579226&fields=NCTId,B...

 

The "full study" call is easier to format but brings in a lot of unneeded data. The "study fields" call is harder to format but brings in the exact information I need. 

The study field call results are also in JSON which is slighlty easier to handle than XML.  Based on your last example which elements of the JSON hierarchy should make it into the final table?

The elements that need to make it into the final table are in the API call:

https://classic.clinicaltrials.gov/api/query/study_fields?expr=AREA[NCTId]NCT02579226&fields=NCTId,B...

 

So each of the fields listed below need to be their own columns in the final table:

  • NCTId
  • BriefTitle
  • LocationFacility
  • LocationStatus
  • LocationCity
  • LocationState
  • LocationZip
  • LocationCountry
  • LocationContactName
  • LocationContactEmail
  • LocationContactPhone

All of those transforms are an attempt to get that original JSON format, shown below, into something easier to work with.

tross4012_0-1690225686103.png

 

apart from the first two these fields all have multiple values. You want to expand these to their own rows?

let
    Source = Excel.Workbook(File.Contents("C:\Users\xxx\Downloads\10examples.xlsx"), null, true),
    Sheet1_Sheet = Source{[Item="Sheet1",Kind="Sheet"]}[Data],
    #"Added Custom" = Table.AddColumn(Sheet1_Sheet, "URL data", each Json.Document( Web.Contents("https://classic.clinicaltrials.gov/api/query/study_fields?expr=AREA[NCTId]" & [Column1] & " &fields=NCTId,BriefTitle,LocationFacility,LocationStatus,LocationCity,LocationState,LocationZip,LocationCountry,LocationContactName,LocationContactEmail,LocationContactPhone&fmt=json"))[StudyFieldsResponse][StudyFields]{0}),
    #"Expanded URL data" = Table.ExpandRecordColumn(#"Added Custom", "URL data", {"Rank", "NCTId", "BriefTitle", "LocationFacility", "LocationStatus", "LocationCity", "LocationState", "LocationZip", "LocationCountry", "LocationContactName", "LocationContactEMail", "LocationContactPhone"})
in
    #"Expanded URL data"

That is correct. In the first screenshot you'll see how the raw data comes in. In the second screenshot you'll see how I, after many transforms, get it formatted.

However, the issue isnt the formatting. The issue is that this formatting is not applied to each NCTId call when I invoke custom function. 

1.tross4012_2-1690226060584.png

 

 

2.tross4012_1-1690226045187.png

 

The custom function is the least of your worries.  The transforms require the use of List.Zip  to glue your separate result column lists into one table.  Aggravated by the fact that some of your lists like LocationContactName are empty.

 

It's a nice challenge for someone who is familiar with Power Query... but we need to figure this out by learning. I'll see what I can come up with.

Sounds good!!! I'll take a look at optimizing the transforms. 

 

As always, your help is much appreciated. 

 

let
    expand = (tbl) => Table.SplitColumn(Table.TransformColumns(Table.FromList(tbl, Splitter.SplitByNothing(), null, null, ExtraValues.Error), {"Column1", each Text.Combine(List.ReplaceValue(_,null,"",Replacer.ReplaceValue), "|"), type text}), "Column1", Splitter.SplitTextByDelimiter("|", QuoteStyle.Csv),{"LocationFacilty","LocationStatus","LocationCity","LocationState","LocationZip","LocationCountry","LocationContactName","LocationContactEmail","LocationContactPhone"}),
    Source = Excel.Workbook(File.Contents("C:\Users\xxx\Downloads\10examples.xlsx"), null, true),
    Sheet1_Sheet = Source{[Item="Sheet1",Kind="Sheet"]}[Data],
    #"Added Custom" = Table.AddColumn(Sheet1_Sheet, "URL data", each Json.Document( Web.Contents("https://classic.clinicaltrials.gov/api/query/study_fields?expr=AREA[NCTId]" & [Column1] & " &fields=NCTId,BriefTitle,LocationFacility,LocationStatus,LocationCity,LocationState,LocationZip,LocationCountry,LocationContactName,LocationContactEmail,LocationContactPhone&fmt=json"))[StudyFieldsResponse][StudyFields]{0}),
    #"Expanded URL data" = Table.ExpandRecordColumn(#"Added Custom", "URL data", {"Rank", "NCTId", "BriefTitle", "LocationFacility", "LocationStatus", "LocationCity", "LocationState", "LocationZip", "LocationCountry", "LocationContactName", "LocationContactEMail", "LocationContactPhone"}),
    #"Added Custom1" = Table.AddColumn(#"Expanded URL data", "Custom", each try expand(List.Zip({[LocationFacility],[LocationStatus],[LocationCity],[LocationState],[LocationZip],[LocationCountry],[LocationContactName],[LocationContactEMail],[LocationContactPhone]})) otherwise #table({"LocationFacilty", "LocationStatus", "LocationCity", "LocationState", "LocationZip", "LocationCountry", "LocationContactName", "LocationContactEmail", "LocationContactPhone"},{{"", "", "", "", "", "", "", "", ""}})),
    #"Replaced Value" = Table.ReplaceValue(#"Added Custom1",each [BriefTitle],each List.First([BriefTitle]),Replacer.ReplaceValue,{"BriefTitle"}),
    #"Removed Other Columns" = Table.SelectColumns(#"Replaced Value",{"Column1", "BriefTitle", "Custom"}),
    #"Expanded Custom" = Table.ExpandTableColumn(#"Removed Other Columns", "Custom", {"LocationFacilty", "LocationStatus", "LocationCity", "LocationState", "LocationZip", "LocationCountry", "LocationContactName", "LocationContactEmail", "LocationContactPhone"})
in
    #"Expanded Custom"

 

This works for the test IDs.  

Note 1: because of the empty lists I had to remove nulls with empty strings

Note 2: The second to last ID has no extra data at all, so I had to introduce a dummy stand-in table

This looks terrific! 

 

The only issue I ran into was with LocationContactName, LocationContactEmail, and LocationContactPhone. In the following example, LocationContactName pulls in both the contact ("Marissa Erickson") and the Principal Investigator ("Mark Daniels, MD"). 

tross4012_0-1690290545519.png

 

If you run the following call for "NCT00097292", you'll see there are more contact names than there are locations due to the Principal Investigator being coupled into the LocationContactName field:

https://classic.clinicaltrials.gov/api/query/study_fields?expr=AREA[NCTId]NCT00097292&fields=NCTId,B...

 

In the screenshot below, you'll see the effect that has the data. To elaborate, "Mark Daniels, MD" is being listed with the "University of California San Francisco" when he is actually a seconday contact at "Childrens Hospital of Orange County", as shown in the first screenshot on this reply.

tross4012_1-1690291028172.png

 

Would it be possible to have a row per contact so that their email and phone number info is not associated with the wrong facility like shown above?

In the screenshot below, you can see how the information gets more difficult to control as this facility has multiple contacts, emails, and phone numbers associated with it. 

 

tross4012_2-1690297550873.png

Not sure what the limitations are here. I tried working with an index as well as a conditional column but have had no luck. 

 

You can plug "NCT00097292" and "NCT00006205" into your excel sheet to get the examples I mentioned loaded in. 

Would it be possible to have a row per contact so that their email and phone number info is not associated with the wrong facility like shown above?

I have no idea how to know what "wrong facility"  means in these cases.  One of the problems of flattening JSON or XML data into a tabular format that it often leads to data destruction (ie dropping of data that doesn't fit the target structure).  Your JSON is in a format that isn't even a proper hierarchy. Does it look any better in XML?

tross4012
Helper I
Helper I

Thanks for the response. 

 

I changed the index to 0:

tross4012_0-1689943667500.png

The issue is that all tables in the invoked "Clean/Format" column point to "NCT02579226" instead of their row's respective index number. 

tross4012_1-1689943739614.png

After clicking on the "Table" record in row 10, it shows the info for row 1 (Index 0).

tross4012_2-1689943797396.png

 

 

please provide sample data that covers your issue. Leave out anything not related to the issue. 

 

https://community.fabric.microsoft.com/t5/Community-Blog/How-to-provide-sample-data-in-the-Power-BI-...
Please show the expected outcome based on the sample data you provided.

https://community.fabric.microsoft.com/t5/Desktop/How-to-Get-Your-Question-Answered-Quickly/m-p/1447...

lbendlin
Super User
Super User

- This is M script, not DAX

- Row numbers start at 0, not at 1.  Change your index definition.

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

Find out what's new and trending in the Fabric Community.