From cd2a3c2419ab22df3a5400f073469b17d3afc20f Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Fri, 13 Oct 2023 12:43:08 +0000 Subject: [PATCH] fix(grapher): remove entities that are not plotted from the entity selector --- .../src/barCharts/DiscreteBarChart.tsx | 18 +++++++++++++++ .../grapher/src/chart/ChartInterface.ts | 1 + .../grapher/src/core/Grapher.tsx | 23 +++++++++++-------- .../grapher/src/lineCharts/LineChart.tsx | 16 +++++++++++++ .../stackedCharts/AbstractStackedChart.tsx | 23 +++++++++++++++++++ .../stackedCharts/StackedDiscreteBarChart.tsx | 22 ++++++++++++++++++ 6 files changed, 94 insertions(+), 9 deletions(-) diff --git a/packages/@ourworldindata/grapher/src/barCharts/DiscreteBarChart.tsx b/packages/@ourworldindata/grapher/src/barCharts/DiscreteBarChart.tsx index f53230fe812..fd3183fde78 100644 --- a/packages/@ourworldindata/grapher/src/barCharts/DiscreteBarChart.tsx +++ b/packages/@ourworldindata/grapher/src/barCharts/DiscreteBarChart.tsx @@ -138,6 +138,24 @@ export class DiscreteBarChart return table } + transformTableForSelection(table: OwidTable): OwidTable { + table = table + .replaceNonNumericCellsWithErrorValues(this.yColumnSlugs) + .dropRowsWithErrorValuesForAllColumns(this.yColumnSlugs) + + if (this.missingDataStrategy === MissingDataStrategy.hide) { + const groupedByEntity = table.groupBy("entityName").map((t) => { + if (t.hasAnyColumnNoValidValue(this.yColumnSlugs)) { + t = t.dropAllRows() + } + return t + }) + table = groupedByEntity[0].concat(groupedByEntity.slice(1)) + } + + return table + } + @computed get inputTable(): OwidTable { return this.manager.table } diff --git a/packages/@ourworldindata/grapher/src/chart/ChartInterface.ts b/packages/@ourworldindata/grapher/src/chart/ChartInterface.ts index b99f3d1b578..7cd9fd39b55 100644 --- a/packages/@ourworldindata/grapher/src/chart/ChartInterface.ts +++ b/packages/@ourworldindata/grapher/src/chart/ChartInterface.ts @@ -31,6 +31,7 @@ export interface ChartInterface { // Todo: should all charts additionally have a placedSeries: ChartPlacedSeries[] getter? transformTable: ChartTableTransformer + transformTableForSelection?: ChartTableTransformer yAxis?: HorizontalAxis | VerticalAxis xAxis?: HorizontalAxis | VerticalAxis diff --git a/packages/@ourworldindata/grapher/src/core/Grapher.tsx b/packages/@ourworldindata/grapher/src/core/Grapher.tsx index d06c08da45d..0519ac89019 100644 --- a/packages/@ourworldindata/grapher/src/core/Grapher.tsx +++ b/packages/@ourworldindata/grapher/src/core/Grapher.tsx @@ -624,16 +624,21 @@ export class Grapher // Depending on the chart type, the criteria for being able to select an entity are // different; e.g. for scatterplots, the entity needs to (1) not be excluded and // (2) needs to have data for the x and y dimension. + let table = + this.isScatter || this.isSlopeChart + ? this.tableAfterAuthorTimelineAndActiveChartTransform + : this.inputTable + + if (!this.isReady) return table + + // Some chart types (e.g. stacked area charts) choose not to show an entity + // with incomplete data. Such chart types define a custom transform function + // to ensure that the entity selector only offers entities that are actually plotted. + if (this.chartInstance.transformTableForSelection) { + table = this.chartInstance.transformTableForSelection(table) + } - if (this.isScatter || this.isSlopeChart) - // for scatter and slope charts, the `transformTable()` call takes care of removing - // all entities that cannot be selected - return this.tableAfterAuthorTimelineAndActiveChartTransform - - // for other chart types, the `transformTable()` call would sometimes remove too many - // entities, and we want to use the inputTable instead (which should have exactly the - // entities where data is available) - return this.inputTable + return table } // If an author sets a timeline filter run it early in the pipeline so to the charts it's as if the filtered times do not exist diff --git a/packages/@ourworldindata/grapher/src/lineCharts/LineChart.tsx b/packages/@ourworldindata/grapher/src/lineCharts/LineChart.tsx index 5835fa5950e..dba6b00d403 100644 --- a/packages/@ourworldindata/grapher/src/lineCharts/LineChart.tsx +++ b/packages/@ourworldindata/grapher/src/lineCharts/LineChart.tsx @@ -300,6 +300,22 @@ export class LineChart return table } + transformTableForSelection(table: OwidTable): OwidTable { + table = table.replaceNonNumericCellsWithErrorValues(this.yColumnSlugs) + + if (this.missingDataStrategy === MissingDataStrategy.hide) { + const groupedByEntity = table.groupBy("entityName").map((t) => { + if (t.hasAnyColumnNoValidValue(this.yColumnSlugs)) { + t = t.dropAllRows() + } + return t + }) + table = groupedByEntity[0].concat(groupedByEntity.slice(1)) + } + + return table + } + @computed private get missingDataStrategy(): MissingDataStrategy { return this.manager.missingDataStrategy || MissingDataStrategy.auto } diff --git a/packages/@ourworldindata/grapher/src/stackedCharts/AbstractStackedChart.tsx b/packages/@ourworldindata/grapher/src/stackedCharts/AbstractStackedChart.tsx index fac3b096c41..ada3c35630a 100644 --- a/packages/@ourworldindata/grapher/src/stackedCharts/AbstractStackedChart.tsx +++ b/packages/@ourworldindata/grapher/src/stackedCharts/AbstractStackedChart.tsx @@ -84,6 +84,29 @@ export class AbstractStackedChart return table } + transformTableForSelection(table: OwidTable): OwidTable { + table = table + .replaceNonNumericCellsWithErrorValues(this.yColumnSlugs) + .dropRowsWithErrorValuesForAllColumns(this.yColumnSlugs) + + if (this.shouldRunLinearInterpolation) { + this.yColumnSlugs.forEach((slug) => { + table = table.interpolateColumnLinearly(slug) + }) + } + + if (this.missingDataStrategy !== MissingDataStrategy.show) { + const groupedByEntity = table + .groupBy("entityName") + .map((t: OwidTable) => + t.dropRowsWithErrorValuesForAnyColumn(this.yColumnSlugs) + ) + table = groupedByEntity[0].concat(groupedByEntity.slice(1)) + } + + return table + } + @computed private get missingDataStrategy(): MissingDataStrategy { return this.manager.missingDataStrategy || MissingDataStrategy.auto } diff --git a/packages/@ourworldindata/grapher/src/stackedCharts/StackedDiscreteBarChart.tsx b/packages/@ourworldindata/grapher/src/stackedCharts/StackedDiscreteBarChart.tsx index 50acfa5f348..a6f0f0e39fb 100644 --- a/packages/@ourworldindata/grapher/src/stackedCharts/StackedDiscreteBarChart.tsx +++ b/packages/@ourworldindata/grapher/src/stackedCharts/StackedDiscreteBarChart.tsx @@ -142,6 +142,28 @@ export class StackedDiscreteBarChart return table } + transformTableForSelection(table: OwidTable): OwidTable { + table = table + .replaceNonNumericCellsWithErrorValues(this.yColumnSlugs) + .dropRowsWithErrorValuesForAllColumns(this.yColumnSlugs) + + this.yColumnSlugs.forEach((slug) => { + table = table.interpolateColumnWithTolerance(slug) + }) + + if (this.missingDataStrategy === MissingDataStrategy.hide) { + const groupedByEntity = table.groupBy("entityName").map((t) => { + if (t.hasAnyColumnNoValidValue(this.yColumnSlugs)) { + t = t.dropAllRows() + } + return t + }) + table = groupedByEntity[0].concat(groupedByEntity.slice(1)) + } + + return table + } + @computed get sortConfig(): SortConfig { return this.manager.sortConfig ?? {} }