Filters and cross-filters¶
Exercise filters-and-cross-filters-annex.pdf · PDF
You open the Steam store and search for a game. Next to the results there is a panel: narrow by price, narrow by tag. You tick one box and the whole list changes. Not one game. All of it.
Your Steam market dashboard says the median price is 4.99. But our indie studio hopes to make a hit. Is 4.99 the median price of hits? Nobody knows: the dashboard only answers for the whole market. Do you build a second dashboard for hits? A third for 2018? No. You keep one dashboard and let the reader choose the slice.
What you will learn
- Add a Value filter and a Time range filter to a dashboard, and apply them
- Explain a filter as a
WHEREthat Superset writes into every chart in its scope - Change the scope of a filter so that one chart ignores it, and say why
- Make one filter depend on another
- Use cross-filtering by clicking a chart, and tell it apart from a filter in the bar
- Avoid the trap: why a filtered KPI can be a true number with a false story
One control, every chart reacts¶
A filter (Superset calls it a native filter) is a control on the dashboard that lets the reader keep only some of the rows. Every chart it reaches is drawn again with those rows only.
It is the panel of the store. One control on the side, and everything on the page obeys it.
Filters live in the filter bar, the strip on the left of the dashboard. Add the first one:
| Step | Do this | You should see |
|---|---|---|
| 1 | Open the filter bar: the arrow at the top of the thin strip on the left | The bar opens |
| 2 | Click the gear icon → Add or edit filters | The filter dialog |
| 3 | Filter name: Owners tier. Filter Type: Value. Dataset: games_clean. Column: owners_tier. Save |
A control called Owners tier in the bar |
| 4 | In the bar, choose Hit and press Apply filters |
The whole KPI row changes |
Look at the top row before and after:
| KPI | Whole market | With Owners tier = Hit |
|---|---|---|
| Games | 26,685 | 623 |
| Free share | 11.6% | 29.2% |
| Median price | 4.99 | 9.99 |
| Hits | 623 | 623 |
There is the answer for the studio. Among the hits, the median price is 9.99: twice the market median. And almost a third of the hits are free.
Careful: choosing is not applying
You pick a value and nothing happens. That is normal: the charts wait until you press Apply filters at the bottom of the bar. The same goes for Clear all. It empties the controls, but the charts keep the old filter until you apply again.
The hidden WHERE¶
How did the median jump from 4.99 to 9.99? Open the three dots of the Games KPI → View query. Superset shows the SQL behind the chart, and there is a new line in it:
WHERE owners_tier IN ('Hit')
You have written that clause by hand since Unit 1 (SQL Lab: filters). A dashboard filter is nothing more than a WHERE that Superset writes for the reader, into the query of every chart it reaches.
flowchart LR
R["<b>Reader</b><br>chooses Hit,<br>presses Apply filters"] --> F["<b>Filter</b><br>Owners tier"]
F -- "adds WHERE owners_tier IN ('Hit')" --> Q1["<b>Query</b> of KPI Games"]
F -- "adds the same WHERE" --> Q2["<b>Query</b> of KPI Median price"]
F -- "adds the same WHERE" --> Q3["<b>Query</b> of the line chart"]
Q1 --> D[("<b>Database</b><br>games_clean")]
Q2 --> D
Q3 --> D
You can prove it without the dashboard. Run the four KPIs yourself in SQL Lab with that WHERE:
SELECT COUNT(*) AS games,
ROUND(100 * AVG(is_free::int), 1) AS free_pct,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY price) AS median_price,
COUNT(*) FILTER (WHERE owners_tier = 'Hit') AS hits
FROM games_clean
WHERE owners_tier IN ('Hit');
| games | free_pct | median_price | hits |
|---|---|---|---|
| 623 | 29.2 | 9.99 | 623 |
The same numbers as the dashboard. No magic: a query.
Careful: a filter does not hide, it recalculates
"The filter hides some data on the screen." It does more than that. Every chart runs its query again with one more WHERE. A median cannot be "hidden": it has to be computed again on the 623 rows that are left. That is why it changes.
Two kinds of filter: Value and Time range¶
| Filter type | The reader chooses | Good for | Our example |
|---|---|---|---|
| Value | One or more values of a column, from a list | Categories | owners_tier = Hit, price_band = Free |
| Time range | A start date and an end date | Anything with a date | Games released in 2018 |
A Time range filter needs more care, because of how the end works. To keep the games of 2018:
| Step | Do this | You should see |
|---|---|---|
| 1 | Add or edit filters → Add filter. Filter Type: Time range. Name: Release date. Save |
A control that says No filter |
| 2 | Click it. Range type: Custom | The date boxes |
| 3 | Change Start (inclusive) to Specific Date/Time and type 2018-01-01. In End (exclusive) type 2019-01-01 |
Both dates set |
| 4 | Press APPLY, then Apply filters | Games reads 8,845 and Hits reads 37 |
Read the two labels again: the start is inclusive, the end is exclusive. The start date is in. The end date is out. So "all of 2018" ends on 2019-01-01, not on 2018-12-31. In SQL it is the pair you already know:
WHERE release_date >= '2018-01-01' AND release_date < '2019-01-01'
If your Games KPI is close to 8,845 but not equal, your dates are off by a day.
Scope: who obeys the filter¶
With 2018 applied, look at the line chart of games per year. It now has one single point. A history chart with one year of history is useless.
Should every chart obey every filter? No.
The scope of a filter is the set of charts it reaches. A chart outside the scope ignores the filter completely.
In the store, the price panel changes the list of results, but not the banner at the top of the page. The banner is out of scope.
| Step | Do this | You should see |
|---|---|---|
| 1 | Add or edit filters → select Release date → Scoping |
A tree of charts under All panels |
| 2 | Untick the line chart. Save | The dialog closes |
| 3 | If saving put Release date back to No filter, set 2018 again and press Apply filters |
KPIs say 8,845, and the line still runs from 2004 to 2018 |
flowchart LR
F["<b>Filter</b><br>Release date = 2018"]
subgraph IN ["<b>In scope</b>: recalculated for 2018"]
K["The four KPIs"]
P["Price band chart"]
end
subgraph OUT ["<b>Out of scope</b>: unchanged"]
L["Line chart<br>games per year, 2004 to 2018"]
end
F -- "adds its WHERE" --> IN
F -. "ignored" .-> OUT
Careful: a filter does not always touch the whole dashboard
As a reader, never assume every chart on the screen shows the same slice. As an author, if you take a chart out of scope, make it obvious: a header such as The whole period, 2004–2018 above the line chart saves the reader from a wrong conclusion.
Dependent filters: a list that shrinks¶
Add a Value filter named Publisher on the column publisher. Open it and scroll. The list never ends: the table has 13,951 different publishers.
SELECT COUNT(DISTINCT publisher) AS publishers,
COUNT(DISTINCT publisher) FILTER (WHERE owners_tier = 'Hit') AS with_a_hit
FROM games_clean;
| publishers | with_a_hit |
|---|---|
| 13951 | 336 |
Only 336 of them have ever published a hit. If the reader has already chosen Hit, why show the other thirteen thousand?
A dependent filter is a filter whose list of values is cut down by the choice made in another filter.
Imagine the panel of the store doing the same: once you tick a genre, the list of publishers only offers those that have a game in that genre.
| Step | Do this | You should see |
|---|---|---|
| 1 | Add a Value filter named Publisher on the column publisher |
A new control |
| 2 | In its configuration, tick Values are dependent on other filters and choose Owners tier. Save |
The dialog closes |
| 3 | Clear all, Apply filters. Open Publisher |
1000 options |
| 4 | Choose Owners tier = Hit. Open Publisher again |
336 options: only publishers that have a hit |
| 5 | Choose Valve and press Apply filters |
Games reads 22 |
Two details. First, the option Values are dependent on other filters only appears when the dashboard already has another filter. Second, why 1000 options and not 13,951? A filter loads at most 1,000 values, in alphabetical order. Without the dependency, Valve is not even in the list. With Hit chosen, it is. Valve is the publisher with the most hits: 22.
Cross-filtering: the chart is the control¶
So far you, the author, decided which questions the reader can ask. But a reader looking at the pie of price bands may wonder: what about the free games only? There is no filter for that. Do they have to ask you?
Cross-filtering means clicking on a part of a chart (a slice, a bar) to filter the other charts of the dashboard by that value.
In the store, it is clicking a tag on a game's page: no panel, you just click what you are looking at.
| Step | Do this | You should see |
|---|---|---|
| 1 | Clear all, Apply filters. In the gear menu, check that Enable cross-filtering is ticked | It is ticked by default |
| 2 | Click the Free slice of your price-band pie |
The other charts react. The bar shows the selection under Cross-filters |
| 3 | Read the KPIs. Then click the slice again | Games 3,094 and Hits 182, then back to the whole market |
Not every chart can be clicked
A Bar Chart with the price bands on its X-axis does not react to clicks. If that is what you have: three dots → Edit chart, change the chart type to Pie Chart with Dimensions price_band, and save it as a new chart called UT4 · Price band pie. Then add it to Steam market.
Under the hood a cross-filter does the same as a filter: it adds a WHERE to the other charts. The difference is who is in charge.
| Filter in the bar | Cross-filter | |
|---|---|---|
| Who sets it up | The author, in advance | Nobody: the reader clicks a chart |
| Good for | The questions you expect (tier, year) | The question that comes up while looking |
| Visible as | A named control, always there | A tag under Cross-filters, gone with a click |
Careful: more filters is not a better dashboard
Each filter is a question you expect the reader to ask. Ten controls nobody uses are noise, exactly like ten charts nobody reads. Two or three good filters beat a wall of dropdowns.
The 2018 trap: a true number, a false story¶
Put the four slices side by side:
| KPI | All | Hit |
2018 | Free |
|---|---|---|---|---|
| Games | 26,685 | 623 | 8,845 | 3,094 |
| Free share | 11.6% | 29.2% | 12.1% | 100.0% |
| Median price | 4.99 | 9.99 | 3.99 | 0.00 |
| Hits | 623 | 623 | 37 | 182 |
Look at the 2018 column. That year has a third of all the games in the table (8,845 of 26,685) but only 37 of the 623 hits. Were the games of 2018 worse?
No. They were younger. A game released in December 2018 had only weeks to find owners when the data was collected. A game from 2012 had six years. The filter changed the year, and something else changed with it without telling you: the time each game had to sell.
The number 37 is true. The story "2018 games are worse" is false. The filter gave you both.
Two habits protect you:
- Say what was filtered before you quote the number. Not "the median price is 9.99", but "among the 623 games with at least a million owners, half cost 9.99 or less, twice the median of the whole market".
- Ask what else changed with the filter. A slice is rarely different in one way only.
If the KPIs look stuck on old numbers
A filter or a cross-filter is still on. Press Clear all, then Apply filters, and look under Cross-filters for a forgotten selection.
Key takeaways¶
- A filter is a control in the filter bar that lets the reader choose a slice. Nothing changes until Apply filters is pressed.
- A filter is a hidden
WHERE: every chart in its scope runs its query again. Check it with View query. - Value filters choose categories; Time range filters choose dates, with an inclusive start and an exclusive end.
- The scope decides which charts obey. Take a chart out when the filter would make it useless, like the history line.
- A dependent filter shrinks its list according to another filter. Cross-filtering lets the reader filter by clicking a chart.
- A filtered KPI can be a true number with a false story: say what was filtered, and ask what else changed with it.
Quick check¶
1. What does Superset do to the charts when the reader applies a filter?
- It hides part of each chart on the screen without touching the data
- It adds a WHERE to the query of every chart in the filter's scope and runs the queries again
- It deletes the rows that do not match from the table
- It creates a copy of the dashboard for that slice
A filter is a hidden WHERE. Each chart in scope queries the database again, which is why a median can change from 4.99 to 9.99. The table itself is never modified.
2. You choose Hit in the Owners tier filter and the KPIs do not move. What is the most likely reason?
- The filter only works on pie charts
- The dashboard is in view mode
- You have not pressed Apply filters
- Value filters need a second filter to work
Choosing a value only fills the control. The charts wait for Apply filters. The same is true after Clear all.
3. You want exactly the games released in 2018 with a Time range filter. Which dates do you type?
- Start 2018-01-01, end 2018-12-31
- Start 2018-01-01, end 2019-01-01
- Start 2017-12-31, end 2018-12-31
- Start 2018-01-01, end 2018-01-01
The start is inclusive and the end is exclusive: the end date itself is left out. Ending on 2018-12-31 would drop the games released on the last day of the year.
4. With the 2018 filter on, your line chart of games per year shows one single point. What is the right fix?
- Delete the line chart from the dashboard
- Delete the Release date filter
- Change the scope of the filter so that the line chart ignores it
- Turn the line chart into a Big Number
The scope is the set of charts a filter reaches. Untick the line chart under Scoping and it keeps showing 2004 to 2018 while the KPIs follow the filter.
5. The Publisher filter says '1000 options'. After choosing Owners tier = Hit it says '336 options'. Why?
- Superset removed the publishers with long names
- The other publishers were deleted from games_clean
- Publisher is a dependent filter: its list is cut down to the publishers that have at least one hit
- A filter can never show more than 336 values when another filter is active
A dependent filter takes its list from the rows left by another filter. Only 336 of the 13,951 publishers have a hit, so the list shrinks and Valve becomes easy to find.
6. What is the main difference between a filter in the bar and a cross-filter?
- A filter changes the queries; a cross-filter only changes colours
- A cross-filter is permanent; a filter disappears when you click
- A filter works on dates only; a cross-filter works on numbers only
- A filter is prepared by the author in advance; a cross-filter is improvised by the reader by clicking a chart
Both add a WHERE to the other charts. The difference is the owner: the author designs filters for the questions they expect, and cross-filtering serves the question that comes up while looking.
7. A dashboard of school marks has the filter 'Group = 2nd DAM' applied and shows 'Average mark: 7.8'. Pick the two things you must do before repeating that number.
- Say what was filtered: it is the average of 2nd DAM, not of the school
- Nothing: a number on a dashboard is always about all the data
- Ask what else changes with the filter, for example how many students or which subjects are behind that average
- Remove the filter bar so that nobody can change the number
This is the 2018 trap in another costume. A filtered KPI is true for its slice only, and a slice usually differs in more than one way. Say what was filtered and ask what else changed.
Your dashboard now answers many questions instead of one. But so far only you can see it. Next: Publishing and permissions, or who gets to open your work.