Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add more metrics on the country_map in Apache-superset?

I am using country_map in apache-superset for visualization purposes. When zooming in on a polygon, information from the columns appears inside of the polygon, like so:

map

There is only one available metric option to display: metric

Code for the metric update is found on this path:

superset/assets/src/visualizations/CountryMap/CountryMap.js

Code:

const updateMetrics = function (region) {
  if (region.length > 0) {     
    resultText.text(format(region[0].metric));
  }
};

The metrics are defined in controls.jsx:

/superset/static/assets/src/explore/controls.jsx

const metrics = {
  type: 'MetricsControl',
  multi: true,
  label: t('Metrics'),
  validators: [v.nonEmpty],
  default: (c) => {
    const metric = mainMetric(c.savedMetrics);
    return metric ? [metric] : null;
  },
  mapStateToProps: (state) => {
    const datasource = state.datasource;
    return {
      columns: datasource ? datasource.columns : [],
      savedMetrics: datasource ? datasource.metrics : [],
      datasourceType: datasource && datasource.type,
    };
  },
  description: t('One or many metrics to display'),
};
const metric = {
  ...metrics,
  multi: false,
  label: t('Metric'),
  default: props => mainMetric(props.savedMetrics),
};

Country map is using metric, which doesn't allow multiple metrics to be selected, Code found here:

superset/assets/src/explore/controlPanels/CountryMap.js

  controlPanelSections: [
    {
      label: t('Query'),
      expanded: true,
      controlSetRows: [
        ['entity'],
        ['metric'],
        ['adhoc_filters'],
      ],
    },
    {
      label: t('Options'),
      expanded: true,
      controlSetRows: [
        ['select_country', 'number_format'],
        ['linear_color_scheme'],
      ],
    },
  ],

The python class of country_map is located at viz.py:

class CountryMapViz(BaseViz):

    """A country centric"""

    viz_type = 'country_map'
    verbose_name = _('Country Map')
    is_timeseries = False
    credits = 'From bl.ocks.org By john-guerra'

    def query_obj(self):
        qry = super(CountryMapViz, self).query_obj()
        qry['metrics'] = [
            self.form_data['metric']]
        qry['groupby'] = [self.form_data['entity']]
        return qry

Changing the code in CountryMap.js and viz.py from metric to metrics results in the following error:

Traceback (most recent call last):
  File "/Documents/superset/superset/superset/viz.py", line 410, in get_df_payload
    df = self.get_df(query_obj)
  File "/Documents/superset/superset/superset/viz.py", line 213, in get_df
    self.results = self.datasource.query(query_obj)
  File "/Documents/superset/superset/superset/connectors/sqla/models.py", line 797, in query
    sql = self.get_query_str(query_obj)
  File "/Documents/superset/superset/superset/connectors/sqla/models.py", line 471, in get_query_str
    qry = self.get_sqla_query(**query_obj)
  File "/Documents/superset/superset/superset/connectors/sqla/models.py", line 585, in get_sqla_query
    elif m in metrics_dict:
TypeError: unhashable type: 'list'

How can I add more metrics to display inside the polygon?

like image 519
Snow Avatar asked Feb 11 '19 09:02

Snow


People also ask

How do I create a dataset Superset?

Registering a new table​ Now that you've configured a data source, you can select specific tables (called Datasets in Superset) that you want exposed in Superset for querying. Navigate to Data ‣ Datasets and select the + Dataset button in the top right corner. A modal window should pop up in front of you.


1 Answers

The direct cause of the error TypeError: unhashable type: 'list' is your modification to file "viz.py":

self.form_data['metric']] to self.form_data['metrics']], in the query_obj(self) method.

As you can see in the source code here, form data metrics is a list object that contains metric, where metric is probably a string or other hashable object. In python language, a list object is not hashable. Because you replace a hashable object (metric) with an unhashable one (metrics), an unhashable type error is then raised.

The correct way to modify CoutryMapViz.query_obj() to accept metrics query can be found in the other Viz classes. The code section here is a very nice example:


class CalHeatmapViz(BaseViz):

"""Calendar heatmap."""
...

    def query_obj(self):
        d = super(CalHeatmapViz, self).query_obj()
        fd = self.form_data
        d['metrics'] = fd.get('metrics')
        return d

Finally, the CoutryMapViz.query_obj() method should look like this:

class CountryMapViz(BaseViz):

...

    def query_obj(self):
        qry = super(CountryMapViz, self).query_obj()
        qry['metrics'] = fd.get('metrics')
        qry['groupby'] = [self.form_data['entity']]
        return qry
like image 94
gdlmx Avatar answered Oct 17 '22 10:10

gdlmx