From e13914d552c9193df8c3b82ae9511791d7de6033 Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Tue, 21 Aug 2018 22:58:47 -0700 Subject: [PATCH] [bugfix] geohash lat/long is reversed (#5695) * [bugfix] geohash lat/long is reversed This allows support for reversing geohashes. Note that the default option was the wrong way. * addressing comments * make reverse_geohash_decode a staticmethod --- .../components/controls/SpatialControl.jsx | 17 +++++++++--- superset/viz.py | 27 ++++++++++++------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/superset/assets/src/explore/components/controls/SpatialControl.jsx b/superset/assets/src/explore/components/controls/SpatialControl.jsx index d9db801c4b0ba..97e6b0c3e4f12 100644 --- a/superset/assets/src/explore/components/controls/SpatialControl.jsx +++ b/superset/assets/src/explore/components/controls/SpatialControl.jsx @@ -51,6 +51,7 @@ export default class SpatialControl extends React.Component { }; this.toggleCheckbox = this.toggleCheckbox.bind(this); this.onChange = this.onChange.bind(this); + this.renderReverseCheckbox = this.renderReverseCheckbox.bind(this); } componentDidMount() { this.onChange(); @@ -75,6 +76,7 @@ export default class SpatialControl extends React.Component { } } else if (type === spatialTypes.geohash) { value.geohashCol = this.state.geohashCol; + value.reverseCheckbox = this.state.reverseCheckbox; if (!value.geohashCol) { errors.push(errMsg); } @@ -120,6 +122,13 @@ export default class SpatialControl extends React.Component { /> ); } + renderReverseCheckbox() { + return ( + + {t('Reverse lat/long ')} + + ); + } renderPopover() { return ( @@ -150,12 +159,11 @@ export default class SpatialControl extends React.Component { > - Column + {t('Column')} {this.renderSelect('lonlatCol', spatialTypes.delimited)} - {t('Reverse lat/long ')} - + {this.renderReverseCheckbox()} @@ -169,6 +177,9 @@ export default class SpatialControl extends React.Component { Column {this.renderSelect('geohashCol', spatialTypes.geohash)} + + {this.renderReverseCheckbox()} +
diff --git a/superset/viz.py b/superset/viz.py index 14627488ff5fc..5f4cea84984ae 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -2101,10 +2101,24 @@ def parse_coordinates(s): _('Invalid spatial point encountered: %s' % s)) return (p.latitude, p.longitude) + @staticmethod + def reverse_geohash_decode(geohash_code): + lat, lng = geohash.decode(geohash_code) + return (lng, lat) + + @staticmethod + def reverse_latlong(df, key): + df[key] = [ + tuple(reversed(o)) + for o in df[key] + if isinstance(o, (list, tuple)) + ] + def process_spatial_data_obj(self, key, df): spatial = self.form_data.get(key) if spatial is None: raise ValueError(_('Bad spatial key')) + if spatial.get('type') == 'latlong': df[key] = list(zip( pd.to_numeric(df[spatial.get('lonCol')], errors='coerce'), @@ -2113,19 +2127,14 @@ def process_spatial_data_obj(self, key, df): elif spatial.get('type') == 'delimited': lon_lat_col = spatial.get('lonlatCol') df[key] = df[lon_lat_col].apply(self.parse_coordinates) - - if spatial.get('reverseCheckbox'): - df[key] = [ - tuple(reversed(o)) if isinstance(o, (list, tuple)) else (0, 0) - for o in df[key] - ] del df[lon_lat_col] elif spatial.get('type') == 'geohash': - latlong = df[spatial.get('geohashCol')].map(geohash.decode) - df[key] = list(zip(latlong.apply(lambda x: x[0]), - latlong.apply(lambda x: x[1]))) + df[key] = df[spatial.get('geohashCol')].map(self.reverse_geohash_decode) del df[spatial.get('geohashCol')] + if spatial.get('reverseCheckbox'): + self.reverse_latlong(df, key) + if df.get(key) is None: raise NullValueException(_('Encountered invalid NULL spatial entry, \ please consider filtering those out'))