17

I am using country_map in 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?

2
  • What did you modify exactly? Could you post your modification to CountryMap.js and viz.py?
    – gdlmx
    Commented Mar 7, 2019 at 9:31
  • @gdlmx In CountryMap.js I changed ['metric'] to ['metrics']. I did the same in viz.py, at the CountryMapViz class, where I just modified self.form_data['metric']] to self.form_data['metrics']], in the query_obj(self) method.
    – Snow
    Commented Mar 7, 2019 at 9:56

1 Answer 1

1

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
4
  • This change however does not make a difference in the metrics shown inside the polygon. Even if you select more than 1 metric in the form, only the first selected metric will be shown when you hover on or click the polygons
    – Snow
    Commented Mar 7, 2019 at 14:39
  • This is to do with the get_data method. You can use the codes in the CalHeatmapViz.get_data() function as an example.
    – gdlmx
    Commented Mar 7, 2019 at 17:47
  • To make the chart display correct, you need to modify the propTypes in CountryMap.js and CoutryMapViz.get_data() in viz.py. This is another question that worth to be discussed in another post.
    – gdlmx
    Commented Mar 7, 2019 at 17:58
  • my question however is not about getting rid of the Type error, but rather about the end result being functional. But regardless, thanks for your contribution and the suggestions in the comment
    – Snow
    Commented Mar 8, 2019 at 11:29

Not the answer you're looking for? Browse other questions tagged or ask your own question.