Basketballs stats – from phone Notes to Power BI

Yesterday, my son tended a 3 team basketball tournament so I though I’d track his stats for the two games on my phone and later find a way to convert that into a stat table. I was aiming for a stat sheet layout similar to this one from ESPN. Version 1.0 will be without the OPP and RESULT columns though.

At the time, all my imagination could come up with for collecting these figures, was the note app on my iPhone. It was easy enough to fill in that I could follow as the game progressed.

In the first game he totaled: 2 assists, 0/5 from three, 4/8 within the arc, 0/1 from the free-throw line , 0 rebounds, 1 steal, 0 blocks, fouls and turnovers in 24 minutes playing time. In his own words – not his best game to date – but they ended up winning both games. 😊

I used the same template for the 2nd game, and my intention was to import the data into Power BI from text. I visited icloud.com in my browser, where i can see my notes.

From here I copy the content of the notes ‘Game1’ and ‘Game2’ into notepad in order to save it as text. To my knowledge, there is no “citizen developer method” for connecting to data stored anywhere in Apple’s iCloud. I named the file with todays date. The file looks like this.

In Power BI I used the ‘From folder’ connector which, if I get this right, will enable me to add new stat sheets based on the same note template, to the folder and just refresh the model.

Power Query Transformations

Connecting to a folder, you get a list of the files in that folder and any subfolders. For this query we only want to work with .txt files so first step is a filter ensuring that.

"Filtered Rows" = Table.SelectRows(Source, each [Extension] = ".txt"), 

Fist file contains lines of text related to two separate games. Second query step is to split this text file into a list of games, and then each game into a list of stats.

#"Added Custom" = Table.AddColumn(#"Filtered Rows", "Stats", each 
    let
        BinaryToText = Text.FromBinary([Content]),
        /*Split Text into list of game texts*/
        SplitGames = List.Skip(Text.Split(BinaryToText,"Game"),1),
        /*for each game split text into list of stats*/
        SplitStats = List.Transform(SplitGames, each Text.Split(_,"#(lf)"))
    in
        SplitStats
),

Remove other columns and expand the list of games(Stats column). Now I add the “Game #”, which is the first value in each list of stats.

Next in order is expanding the Stats column yet again to get a row for each stat per game. Filter the table to only those rows containing “:” in the Stats column and splitting by the “:” delimiter.

The “Stats.2” column is subsequently cleaned up using Text.Clean() and Text.Trim() and blanks are replaced with nulls before Stat.1 is pivoted with Stat.2 as values without any aggregation. Now we have a row for each game with a column for each collected stat.

Counting or Summing values in a text string

When collecting these stats the focus was on making the the collection easy and then turning it tabular in power query. This was done using two custom functions to create the stat columns which will be loaded to model.

fxCount – counts the number of characters in a text string, using Text.Length(), which will be used for turning the string “01001110” from the Fg column 8 field goal attempts. Simple.

( aString )=>

let
len = Text.Length(aString)
in
len

fxSum – using the Splitter.SplitTextByRepeatedLengths the string “01001110” is split into a list of individual characters which is converted to numbers and summed to return 4 made field goals.

( aString )=>

let
texttolist = Splitter.SplitTextByRepeatedLengths(1,true)(aString),
changetype = List.Transform(texttolist,each Number.From(_)),
sum = List.Sum(changetype)
in
sum

Handling additions with null values

I began invoking functions to end up with the columns i wanted to load to model. To handle the null values when calculating the columns PTS and REB, i used List.Sum as adding a value and null returns null.

Now I do a simple Table.SelectColumns to end up with just the columns i initially wanted and load the data to Power BI.

Next I would change the following in how I collect the stats:
a. I have to handle substitutions and thus a more granular collection of playing time.
b. The stats are saved in a place where I can connect to from Power BI.

Swapping Visuals using Bookmark Navigator

My idea for this post came when I was creating examples for a colleague on how changing the design and functionality of a report page can make it load faster. There are many factors when it comes performance improvements, adding the functionality of swapping visuals can improve performance similar to how a drill through page does it.

Some view working with bookmarks as a cumbersome task. Very understandable, if your bookmark and selection pane looks something like this.

Which even isn’t as bad as it can get. You’ve probably managed to create bookmarks and setup the desired functionality under similar circumstances. But, you dreaded the day a changes request rolled in and that report page had to be updated. So, perhaps you have, like myself and many others, avoided working with bookmarks. But you don’t have to.

Adam and Patrick (Guy in a Cube) has a whole series of videos on the topic, buttons, selections and bookmarks where they cover mastering bookmarks and how to make navigation easier. The only difference from Adam’s video on swapping visuals, is that I now can use the bookmark navigator instead a creating separate buttons for launching each bookmark.

Setup – Grouping and Naming

I’ve created a simple report page using the Adventure Works DW2020 dataset. I want the ability to swap between the ribbon chart showing Sales Units per Category over months and a matrix with the full product hierarchy and Sales Units over months.

  1. The visuals I want to swap are grouped and named ‘VizSwap’. The layering order is not relevant in this case particular case.
  2. A bookmark to show each visual and hide the other. Both of them are set to ‘Display’, ‘Current Page’ and ‘Selected Visuals’
  3. The bookmarks are grouped and the group was renamed to match the report page.

Now, because the visuals I want my bookmarks to affect are grouped, I can easily update them by selecting the ‘VisSwap’ group in the selection pane. Here, I first hide the matrix, I then right click on the ‘Ribbon’ bookmark and click ‘Update’. Now the ‘Ribbon’ bookmark is configured.

The ‘VisSwap’ group should still be selected in the selection pane, so I hide the ‘Ribbon’ and unhide the ‘Matrix’ here. I make sure the ‘VisSwap’ group is selected before I update the ‘Matrix’ bookmark in the bookmarks pane. Similar to how i updated the ‘Ribbon’ bookmark. Grouping the visuals made it really easy for me to update my bookmarks. Clicking each bookmark, the visuals should now swap on the canvas.

Lets bring in the bookmark navigator. It’s located under buttons, in the inserts pane of the ribbon. Now, if I had a swath of bookmarks, similar to what was depicted in the beginning of this post, all of them would be shown in the bookmark navigator, which wouldn’t be useful. But since I’ve grouped my bookmarks, I can select the group ‘Category Sales’ which contains he bookmarks i want to use in this navigator, by going to the Bookmarks section in the Format pane for the bookmark navigator visual.

And now, I can swap my visuals with the bookmark navigator.

Now you know how grouping visual and bookmarks can make working with bookmarks easier for you. I would very much like to hear any workarounds you have when working with bookmarks. Have you incorporated similar functionality in your reports or done something completely different with bookmarks?