From 3ab33f2f3f2886873e986e2f32c0918385284c74 Mon Sep 17 00:00:00 2001 From: Mmoncadaisla Date: Tue, 16 Feb 2021 11:15:30 +0100 Subject: [PATCH 01/26] Fix typo in pg2dtypes function for timestamptz --- cartoframes/utils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cartoframes/utils/utils.py b/cartoframes/utils/utils.py index 492d37a3d..c01228ce2 100644 --- a/cartoframes/utils/utils.py +++ b/cartoframes/utils/utils.py @@ -147,7 +147,7 @@ def pg2dtypes(pgtype): 'boolean': 'bool', 'bool': 'bool', 'date': 'datetime64[D]', 'timestamp': 'datetime64[ns]', 'timestamp without time zone': 'datetime64[ns]', - 'timestampz': 'datetime64[ns]', 'timestamp with time zone': 'datetime64[ns]', + 'timestamptz': 'datetime64[ns]', 'timestamp with time zone': 'datetime64[ns]', 'USER-DEFINED': 'object', } return mapping.get(str(pgtype), 'object') From d34e59fcdc91b736b2c3175efbd1a03e57e9706d Mon Sep 17 00:00:00 2001 From: Mmoncadaisla Date: Tue, 16 Feb 2021 11:26:11 +0100 Subject: [PATCH 02/26] Fix typo on pg2dtypes test --- tests/unit/utils/test_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/utils/test_utils.py b/tests/unit/utils/test_utils.py index c09426882..d28de1cdb 100644 --- a/tests/unit/utils/test_utils.py +++ b/tests/unit/utils/test_utils.py @@ -155,7 +155,7 @@ def test_pg2dtypes(self): 'boolean': 'bool', 'date': 'datetime64[D]', 'timestamp': 'datetime64[ns]', 'timestamp without time zone': 'datetime64[ns]', - 'timestampz': 'datetime64[ns]', 'timestamp with time zone': 'datetime64[ns]', + 'timestamptz': 'datetime64[ns]', 'timestamp with time zone': 'datetime64[ns]', 'USER-DEFINED': 'object', } for i in results: From 63a83a8173b86bc0adc50941edd1c6a3e7bd4d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Tue, 9 Mar 2021 09:23:04 +0100 Subject: [PATCH 03/26] Remove DataObsClient --- CHANGELOG.md | 5 + cartoframes/data/clients/__init__.py | 4 +- cartoframes/data/clients/data_obs_client.py | 716 ------------------ tests/e2e/data/client/test_data_obs_client.py | 417 ---------- 4 files changed, 6 insertions(+), 1136 deletions(-) delete mode 100644 cartoframes/data/clients/data_obs_client.py delete mode 100644 tests/e2e/data/client/test_data_obs_client.py diff --git a/CHANGELOG.md b/CHANGELOG.md index e4aecd058..67f35b9a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [NEXT] - 2021-X-X + +### Removed +- Remove DataObsClient (#) + ## [1.1.1] - 2021-02-12 ### Fixed diff --git a/cartoframes/data/clients/__init__.py b/cartoframes/data/clients/__init__.py index 5c638f58a..a54877d1c 100644 --- a/cartoframes/data/clients/__init__.py +++ b/cartoframes/data/clients/__init__.py @@ -1,7 +1,5 @@ from .sql_client import SQLClient -from .data_obs_client import DataObsClient __all__ = [ - 'SQLClient', - 'DataObsClient' + 'SQLClient' ] diff --git a/cartoframes/data/clients/data_obs_client.py b/cartoframes/data/clients/data_obs_client.py deleted file mode 100644 index bf6a5bbfa..000000000 --- a/cartoframes/data/clients/data_obs_client.py +++ /dev/null @@ -1,716 +0,0 @@ -# -*- coding: utf-8 -*- - -import json -import collections - -from warnings import warn -from pandas import DataFrame -from carto.exceptions import CartoException - -from ...io.carto import read_carto, to_carto -from ...utils import utils -from ...utils.utils import deprecated -from ...io.managers.context_manager import ContextManager - - -@deprecated(message='The Data Observatory v1 is being deprecated. Use the `data.observatory` package instead') -class DataObsClient: - """Data Observatory v1 class (deprecated). `Data Observatory v1 documentation (deprecated) - `__. - - This class provides the following methods to interact with Data Observatory v1 (deprecated): - - boundaries: returns a geopandas.GeoDataFrame with - the geographic boundaries (geometries) or their metadata. - - discovery: returns a pandas.DataFrame with the measures found. - - augment: returns a geopandas.GeoDataFrame with the augmented data. - - Args: - credentials (:py:class:`Credentials `): - A :py:class:`Credentials ` - instance can be used in place of a `username`|`base_url` / `api_key` combination. - """ - - def __init__(self, credentials=None): - self._verbose = 0 - self._credentials = credentials - self._manager = ContextManager(credentials) - - @deprecated(message='The Data Observatory v1 is being deprecated. Use the `data.observatory` package instead') - def boundaries(self, boundary=None, region=None, decode_geom=False, - timespan=None, include_nonclipped=False): - """ - Find all boundaries available for the world or a `region`. If - `boundary` is specified, get all available boundary polygons for the - region specified (if any). This method is especially useful for getting - boundaries for a region and, with :py:meth:`DataObsClient.augment - ` and - :py:meth:`DataObsClient.discovery - `, getting tables of - geometries and the corresponding raw measures. For example, if you want - to analyze how median income has changed in a region (see examples - section for more). - - Args: - boundary (str, optional): - Boundary identifier for the boundaries - that are of interest. For example, US census tracts have a - boundary ID of ``us.census.tiger.census_tract``, and Brazilian - Municipios have an ID of ``br.geo.municipios``. Find IDs by - running :py:meth:`DataObsClient.boundaries - ` - without any arguments, or by looking in the `Data Observatory v1 catalog (deprecated) - `__. - region (str, optional): - Region where boundary information or, - if `boundary` is specified, boundary polygons are of interest. - `region` can be one of the following: - - - table name (str): - Name of a table in user's CARTO account - - bounding box (list of float): - List of four values (two lng/lat pairs) in the following order: - western longitude, southern latitude, eastern longitude, - and northern latitude. - For example, Switzerland fits in - ``[5.9559111595,45.8179931641,10.4920501709,47.808380127]`` - timespan (str, optional): - Specific timespan to get geometries from. - Defaults to use the most recent. See the Data Observatory v1 catalog (deprecated) - for more information. - decode_geom (bool, optional): - Whether to return the geometries as - Shapely objects or keep them encoded as EWKB strings. Defaults - to False. - include_nonclipped (bool, optional): - Optionally include non-shoreline-clipped boundaries. - These boundaries are the raw boundaries provided by, for example, - US Census Tiger. - - Returns: - geopandas.GeoDataFrame: - If `boundary` is specified, then all available - boundaries and accompanying `geom_refs` in `region` (or the world - if `region` is ``None`` or not specified) are returned. If - `boundary` is not specified, then a GeoDataFrame of all available - boundaries in `region` (or the world if `region` is ``None``). - - Examples: - Find all boundaries available for Australia. The columns - `geom_name` gives us the name of the boundary and `geom_id` - is what we need for the `boundary` argument. - - >>> do = DataObsClient(credentials) - >>> au_boundaries = do.boundaries(region='Australia') - >>> au_boundaries[['geom_name', 'geom_id']] - - Get the boundaries for Australian Postal Areas and map them. - - >>> au_postal_areas = do.boundaries(boundary='au.geo.POA') - >>> Map(Layer(au_postal_areas)) - - Get census tracts around Idaho Falls, Idaho, USA, and add median - income from the US census. Without limiting the metadata, we get - median income measures for each census in the - Data Observatory v1 (deprecated). - - >>> # Note: default credentials will be supported in a future release - >>> do = DataObsClient(credentials) - >>> # will return GeoDataFrame with columns `the_geom` and `geom_ref` - >>> tracts = do.boundaries( - ... boundary='us.census.tiger.census_tract', - ... region=[-112.096642,43.429932,-111.974213,43.553539]) - >>> # write geometries to a CARTO table - >>> tracts.upload('idaho_falls_tracts') - >>> # gather metadata needed to look up median income - >>> median_income_meta = do.discovery( - ... 'idaho_falls_tracts', - ... keywords='median income', - ... boundaries='us.census.tiger.census_tract') - >>> # get median income data and original table as new GeoDataFrame - >>> idaho_falls_income = do.augment( - ... 'idaho_falls_tracts', - ... median_income_meta, - ... how='geom_refs') - >>> # overwrite existing table with newly-enriched GeoDataFrame - >>> idaho_falls_income.upload('idaho_falls_tracts', if_exists='replace') - - """ - # TODO: create a function out of this? - if isinstance(region, str): - # see if it's a table - try: - geom_type = self._geom_type(region) - if geom_type in ('point', 'line', ): - bounds = ('(SELECT ST_ConvexHull(ST_Collect(the_geom)) ' - 'FROM {table})').format(table=region) - else: - bounds = ('(SELECT ST_Union(the_geom) ' - 'FROM {table})').format(table=region) - except CartoException: - # see if it's a Data Obs region tag - regionsearch = '"geom_tags"::text ilike \'%{}%\''.format( - get_countrytag(region)) - bounds = 'ST_MakeEnvelope(-180.0, -85.0, 180.0, 85.0, 4326)' - elif isinstance(region, collections.Iterable): - if len(region) != 4: - raise ValueError( - '`region` should be a list of the geographic bounds of a ' - 'region in the following order: western longitude, ' - 'southern latitude, eastern longitude, and northern ' - 'latitude. For example, Switerland fits in ' - '``[5.9559111595,45.8179931641,10.4920501709,' - '47.808380127]``.') - bounds = ('ST_MakeEnvelope({0}, {1}, {2}, {3}, 4326)').format( - *region) - elif region is None: - bounds = 'ST_MakeEnvelope(-180.0, -85.0, 180.0, 85.0, 4326)' - else: - raise ValueError('`region` must be a str, a list of two lng/lat ' - 'pairs, or ``None`` (which defaults to the ' - 'world)') - if include_nonclipped: - clipped = None - else: - clipped = (r"(geom_id ~ '^us\.census\..*_clipped$' OR " - r"geom_id !~ '^us\.census\..*')") - - if boundary is None: - regionsearch = locals().get('regionsearch') - filters = ' AND '.join(r for r in [regionsearch, clipped] if r) - query = utils.minify_sql(( - 'SELECT *', - 'FROM OBS_GetAvailableGeometries(', - ' {bounds}, null, null, null, {timespan})', - '{filters}')).format( - bounds=bounds, - timespan=utils.pgquote(timespan), - filters='WHERE {}'.format(filters) if filters else '') - return self._fetch(query, decode_geom=True) - - query = utils.minify_sql(( - 'SELECT the_geom, geom_refs', - 'FROM OBS_GetBoundariesByGeometry(', - ' {bounds},', - ' {boundary},', - ' {time})', )).format( - bounds=bounds, - boundary=utils.pgquote(boundary), - time=utils.pgquote(timespan)) - return self._fetch(query, decode_geom=decode_geom) - - @deprecated(message='The Data Observatory v1 is being deprecated. Use the `data.observatory` package instead') - def discovery(self, region, keywords=None, regex=None, time=None, - boundaries=None, include_quantiles=False): - """Discover Data Observatory v1 measures (deprecated). This method returns the full - Data Observatory v1 metadata model (deprecated) for each measure or measures that - match the conditions from the inputs. The full metadata in each row - uniquely defines a measure based on the timespan, geographic - resolution, and normalization (if any). Read more about the metadata - response in `Data Observatory v1 (deprecated) - `__ - documentation. - - Internally, this method finds all measures in `region` that match the - conditions set in `keywords`, `regex`, `time`, and `boundaries` (if - any of them are specified). Then, if `boundaries` is not specified, a - geographical resolution for that measure will be chosen subject to the - type of region specified: - - 1. If `region` is a table name, then a geographical resolution that - is roughly equal to `region size / number of subunits`. - 2. If `region` is a country name or bounding box, then a geographical - resolution will be chosen roughly equal to `region size / 500`. - - Since different measures are in some geographic resolutions and not - others, different geographical resolutions for different measures are - oftentimes returned. - - .. tip:: - - To remove the guesswork in how geographical resolutions are - selected, specify one or more boundaries in `boundaries`. See - the boundaries section for each region in the `Data Observatory v1 (deprecated) - catalog `__. - - The metadata returned from this method can then be used to create raw - tables or for augmenting an existing table from these measures using - :py:meth:`DataObsClient.augment `. - For the full Data Observatory v1 catalog (deprecated), visit - https://cartodb.github.io/bigmetadata/. When working with the metadata - DataFrame returned from this method, be careful to only remove rows not - columns as `DataObsClient.augment ` - generally needs the full metadata. - - .. note:: - Narrowing down a discovery query using the `keywords`, `regex`, and - `time` filters is important for getting a manageable metadata - set. Besides there being a large number of measures in the DO, a - metadata response has acceptable combinations of measures with - demonimators (normalization and density), and the same measure from - other years. - - For example, setting the region to be United States counties with - no filter values set will result in many thousands of measures. - - Args: - region (str or list of float): - Information about the region of interest. - `region` can be one of three types: - - - region name (str): - Name of region of interest. Acceptable - values are limited to: 'Australia', 'Brazil', 'Canada', - 'European Union', 'France', 'Mexico', 'Spain', - 'United Kingdom', 'United States'. - - table name (str): - Name of a table in user's CARTO account - with geometries. The region will be the bounding box of - the table. - - .. Note:: If a table name is also a valid Data Observatory v1 (deprecated) - region name, the Data Observatory v1 (deprecated) name will be chosen - over the table. - - - bounding box (list of float): - List of four values (two lng/lat pairs) in the following - order: western longitude, southern latitude, eastern longitude, - and northern latitude. For example, Switzerland fits in - ``[5.9559111595,45.8179931641,10.4920501709,47.808380127]`` - - .. Note:: Geometry levels are generally chosen by subdividing - the region into the next smallest administrative unit. To - override this behavior, specify the `boundaries` flag. For - example, set `boundaries` to - ``'us.census.tiger.census_tract'`` to choose US census - tracts. - - keywords (str or list of str, optional): - Keyword or list of keywords in measure description or name. - Response will be matched on all keywords listed (boolean `or`). - - regex (str, optional): - A regular expression to search the measure - descriptions and names. Note that this relies on PostgreSQL's - case insensitive operator ``~*``. See `PostgreSQL docs - `__ - for more information. - time (str or list of str, optional): - Timespan or list of timespans to filter thje result. - boundaries (str or list of str, optional): - Boundary or list of boundaries that specify the measure resolution. See the - boundaries section for each region in the `Data Observatory v1 - catalog (deprecated) `__. - include_quantiles (bool, optional): - Include quantiles calculations which are a calculation - of how a measure compares to all measures in the full GeoDataFrame. - Defaults to ``False``. If ``True``, quantiles columns will be returned - for each column which has it pre-calculated. - - Returns: - pandas.DataFrame: - A DataFrame of the complete metadata model for specific measures based - on the search parameters. - - Raises: - ValueError: If `region` is a :obj:`list` and does not consist of - four elements, or if `region` is not an acceptable region - CartoException: If `region` is not a table in user account - - Examples: - Get all European Union measures that mention ``freight``. - - >>> freight_meta = do.discovery('European Union', - ... keywords='freight', - ... time='2010') - >>> freight_meta['numer_name'].head() - - """ - if isinstance(region, str): - try: - # see if it's a DO region, nest in {} - countrytag = '\'{{{0}}}\''.format( - get_countrytag(region)) - boundary = ('SELECT ST_MakeEnvelope(-180.0, -85.0, 180.0, ' - '85.0, 4326) AS env, 500::int AS cnt') - except ValueError: - # TODO: make this work for general queries - # see if it's a table - self._manager.execute_query( - 'EXPLAIN SELECT * FROM {}'.format(region)) - boundary = ( - 'SELECT ST_SetSRID(ST_Extent(the_geom), 4326) AS env, ' - 'count(*)::int AS cnt FROM {table_name}').format( - table_name=region) - elif isinstance(region, collections.Iterable): - if len(region) != 4: - raise ValueError( - '`region` should be a list of the geographic bounds of a ' - 'region in the following order: western longitude, ' - 'southern latitude, eastern longitude, and northern ' - 'latitude. For example, Switerland fits in ' - '``[5.9559111595,45.8179931641,10.4920501709,' - '47.808380127]``.' - ) - boundary = ('SELECT ST_MakeEnvelope({0}, {1}, {2}, {3}, 4326) AS ' - 'env, 500::int AS cnt'.format(*region)) - - if locals().get('countrytag') is None: - countrytag = 'null' - - if keywords: - if isinstance(keywords, str): - keywords = [keywords, ] - kwsearch = ' OR '.join( - ('numer_description ILIKE \'%{kw}%\' OR ' - 'numer_name ILIKE \'%{kw}%\'').format(kw=kw) - for kw in keywords) - kwsearch = '({})'.format(kwsearch) - - if regex: - regexsearch = ('(numer_description ~* {regex} OR numer_name ' - '~* {regex})').format(regex=utils.pgquote(regex)) - - if keywords or regex: - subjectfilters = '{kw} {op} {regex}'.format( - kw=kwsearch if keywords else '', - op='OR' if (keywords and regex) else '', - regex=regexsearch if regex else '').strip() - else: - subjectfilters = '' - - if isinstance(time, str) or time is None: - time = [time, ] - if isinstance(boundaries, str) or boundaries is None: - boundaries = [boundaries, ] - - if all(time) and all(boundaries): - bt_filters = 'valid_geom AND valid_timespan' - elif all(time) or all(boundaries): - bt_filters = 'valid_geom' if all(boundaries) else 'valid_timespan' - else: - bt_filters = '' - - if bt_filters and subjectfilters: - filters = 'WHERE ({s}) AND ({bt})'.format( - s=subjectfilters, bt=bt_filters) - elif bt_filters or subjectfilters: - filters = 'WHERE {f}'.format(f=subjectfilters or bt_filters) - else: - filters = '' - - quantiles = ('WHERE numer_aggregate <> \'quantile\'' - if not include_quantiles else '') - - numer_query = utils.minify_sql(( - 'SELECT', - ' numer_id,', - ' {geom_id} AS geom_id,', - ' {timespan} AS numer_timespan,', - ' {normalization} AS normalization', - ' FROM', - ' OBS_GetAvailableNumerators(', - ' (SELECT env FROM envelope),', - ' {countrytag},', - ' null,', # denom_id - ' {geom_id},', - ' {timespan})', - '{filters}', )).strip() - - # query all numerators for all `time`, `boundaries`, and raw/derived - numers = '\nUNION\n'.join( - numer_query.format( - timespan=utils.pgquote(t), - geom_id=utils.pgquote(b), - normalization=utils.pgquote(n), - countrytag=countrytag, - filters=filters) - for t in time - for b in boundaries - for n in ('predenominated', None)) - - query = utils.minify_sql(( - 'WITH envelope AS (', - ' {boundary}', - '), numers AS (', - ' {numers}', - ')', - 'SELECT *', - 'FROM json_to_recordset(', - ' (SELECT OBS_GetMeta(', - ' envelope.env,', - ' json_agg(numers),', - ' 10, 10, envelope.cnt', - ' ) AS meta', - 'FROM numers, envelope', - 'GROUP BY env, cnt)) as data(', - ' denom_aggregate text, denom_colname text,', - ' denom_description text, denom_geomref_colname text,', - ' denom_id text, denom_name text, denom_reltype text,', - ' denom_t_description text, denom_tablename text,', - ' denom_type text, geom_colname text, geom_description text,', - ' geom_geomref_colname text, geom_id text, geom_name text,', - ' geom_t_description text, geom_tablename text,', - ' geom_timespan text, geom_type text, id numeric,', - ' max_score_rank text, max_timespan_rank text,', - ' normalization text, num_geoms numeric, numer_aggregate text,', - ' numer_colname text, numer_description text,', - ' numer_geomref_colname text, numer_id text,', - ' numer_name text, numer_t_description text,', - ' numer_tablename text, numer_timespan text,', - ' numer_type text, score numeric, score_rank numeric,', - ' score_rownum numeric, suggested_name text,', - ' target_area text, target_geoms text, timespan_rank numeric,', - ' timespan_rownum numeric)', - '{quantiles}', )).format( - boundary=boundary, - numers=numers, - quantiles=quantiles).strip() - utils.debug_print(self._verbose, query=query) - return DataFrame(self._fetch(query, decode_geom=True)) - - @deprecated(message='The Data Observatory v1 is being deprecated. Use the `data.observatory` package instead') - def augment(self, table_name, metadata, persist_as=None, how='the_geom'): - """Get an augmented CARTO dataset with `Data Observatory v1 (deprecated) - `__ measures. Use - `DataObsClient.discovery - <#DataObsClient.discovery>`__ to search for available - measures, or see the full `Data Observatory v1 catalog (deprecated) - `__. Optionally - persist the data as a new table. - - Args: - table_name (str): - Name of table on CARTO account that Data Observatory v1 measures (deprecated) - are to be added to. - metadata (pandas.DataFrame): - List of all measures to add to - `table_name`. See :py:meth:`DataObsClient.discovery - ` outputs - for a full list of metadata columns. - persist_as (str, optional): - Output the results of augmenting - `table_name` to `persist_as` as a persistent table on CARTO. - Defaults to ``None``, which will not create a table. - how (str, optional): - Column name for identifying the geometry from which to fetch the data. - Defaults to `the_geom`, which results in measures that are spatially - interpolated (e.g., a neighborhood boundary's population will - be calculated from underlying census tracts). Specifying a - column that has the geometry identifier (for example, GEOID for - US Census boundaries), results in measures directly from the - Census for that GEOID but normalized how it is specified in the - metadata. - - Returns: - geopandas.GeoDataFrame: - A GeoDataFrame representation of `table_name` which - has new columns for each measure in `metadata`. - - Raises: - NameError: - If the columns in `table_name` are in the ``suggested_name`` - column of `metadata`. - ValueError: - If metadata object is invalid or empty, or if the number of - requested measures exceeds 50. - CartoException: - If user account consumes all of Data Observatory v1 (deprecated) quota - - Example: - Get a DataFrame with Data Observatory v1 measures (deprecated) based - on the geometries in a CARTO table. - - >>> do = DataObsClient(credentials) - >>> median_income = do.discovery( - ... 'transaction_events', - ... regex='.*median income.*', - ... time='2011 - 2015') - >>> ds = do.augment('transaction_events', median_income) - - Pass in cherry-picked measures from the Data Observatory v1 catalog (deprecated). - The rest of the metadata will be filled in, but it's important to - specify the geographic level as this will not show up in the column - name. - - >>> median_income = [{'numer_id': 'us.census.acs.B19013001', - ... 'geom_id': 'us.census.tiger.block_group', - ... 'numer_timespan': '2011 - 2015'}] - >>> ds = do.augment('transaction_events', median_income) - - """ - - if isinstance(metadata, DataFrame): - _meta = metadata.copy().reset_index() - elif isinstance(metadata, collections.Iterable): - query = utils.minify_sql(( - 'WITH envelope AS (', - ' SELECT', - ' ST_SetSRID(ST_Extent(the_geom)::geometry, 4326) AS env,', - ' count(*)::int AS cnt', - ' FROM {table_name}', - ')', - 'SELECT *', - ' FROM json_to_recordset(', - ' (SELECT OBS_GetMeta(', - ' envelope.env,', - ' (\'{meta}\')::json,', - ' 10, 1, envelope.cnt', - ' ) AS meta', - ' FROM envelope', - ' GROUP BY env, cnt)) as data(', - ' denom_aggregate text, denom_colname text,', - ' denom_description text, denom_geomref_colname text,', - ' denom_id text, denom_name text, denom_reltype text,', - ' denom_t_description text, denom_tablename text,', - ' denom_type text, geom_colname text,', - ' geom_description text,geom_geomref_colname text,', - ' geom_id text, geom_name text, geom_t_description text,', - ' geom_tablename text, geom_timespan text,', - ' geom_type text, id numeric, max_score_rank text,', - ' max_timespan_rank text, normalization text, num_geoms', - ' numeric,numer_aggregate text, numer_colname text,', - ' numer_description text, numer_geomref_colname text,', - ' numer_id text, numer_name text, numer_t_description', - ' text, numer_tablename text, numer_timespan text,', - ' numer_type text, score numeric, score_rank numeric,', - ' score_rownum numeric, suggested_name text,', - ' target_area text, target_geoms text, timespan_rank', - ' numeric, timespan_rownum numeric)', - )).format(table_name=table_name, - meta=json.dumps(metadata).replace('\'', '\'\'')) - _meta = DataFrame(self._fetch(query)) - - if _meta.shape[0] == 0: - raise ValueError('There are no valid metadata entries. Check ' - 'inputs.') - if _meta.shape[0] > 50: - raise ValueError('The number of metadata entries exceeds 50. Tip: ' - 'If `metadata` is a pandas.DataFrame, iterate ' - 'over this object using `metadata.groupby`. If ' - 'it is a list, iterate over chunks of it. Then ' - 'combine resulting DataFrames using ' - '`pandas.concat`') - - # get column names except the_geom_webmercator - table_columns = self._manager.get_column_names(table_name, exclude=['the_geom_webmercator']) - - names = {} - for suggested in _meta['suggested_name']: - if suggested in table_columns: - names[suggested] = utils.unique_colname(suggested, table_columns) - warn( - '{s0} was augmented as {s1} because of name ' - 'collision'.format(s0=suggested, s1=names[suggested]) - ) - else: - names[suggested] = suggested - - # drop description columns to lighten the query - meta_columns = _meta.columns.values - drop_columns = [] - for meta_column in meta_columns: - if meta_column.endswith('_description'): - drop_columns.append(meta_column) - - if len(drop_columns) > 0: - _meta.drop(drop_columns, axis=1, inplace=True) - - cols = ', '.join( - '(data->{n}->>\'value\')::{pgtype} AS {col}'.format( - n=row[0], - pgtype=row[1]['numer_type'], - col=names[row[1]['suggested_name']]) - for row in _meta.iterrows()) - query = utils.minify_sql(( - 'SELECT {table_cols}, {cols}', - ' FROM OBS_GetData(', - ' (SELECT array_agg({how})', - ' FROM "{tablename}"),', - ' (SELECT \'{meta}\'::json)) as m,', - ' {tablename} as t', - ' WHERE t."{rowid}" = m.id',)).format( - how=('(the_geom, cartodb_id)::geomval' - if how == 'the_geom' else how), - tablename=table_name, - rowid='cartodb_id' if how == 'the_geom' else how, - cols=cols, - table_cols=','.join('t.{}'.format(c) for c in table_columns), - meta=_meta.to_json(orient='records').replace('\'', '\'\'')) - - return self._fetch(query, decode_geom=False, table_name=persist_as) - - def _fetch(self, query, decode_geom=False, table_name=None): - gdf = read_carto(query, self._credentials, decode_geom=decode_geom) - if table_name: - to_carto(gdf, table_name, self._credentials, - geom_col='the_geom', if_exists='replace', log_enabled=False) - return gdf - - def _geom_type(self, table): - """gets geometry type(s) of specified layer""" - query = 'SELECT * FROM "{table}"'.format(table=table) - return self._manager.get_geom_type(query) - - -# Country names are pegged to the following query: -# SELECT -# count(*) num_measurements, -# tag.key region_id, -# tag.value region_name -# FROM ( -# SELECT * -# FROM OBS_GetAvailableNumerators() -# WHERE jsonb_pretty(numer_tags) LIKE '%subsection/%' -# ) numers, -# Jsonb_Each(numers.numer_tags) tag -# WHERE tag.key like 'section%' -# GROUP BY tag.key, tag.value -# ORDER BY region_name - - -REGIONTAGS = { - 'Australia': 'section/tags.au', - 'Brazil': 'section/tags.br', - 'Canada': 'section/tags.ca', - 'European Union': 'section/tags.eu', - 'France': 'section/tags.fr', - 'Mexico': 'section/tags.mx', - 'Spain': 'section/tags.spain', - 'United Kingdom': 'section/tags.uk', - 'United States': 'section/tags.united_states' -} - - -def get_countrytag(country): - """normalize country name to match data obs""" - norm_name = { - 'australia': 'Australia', - 'brazil': 'Brazil', - 'brasil': 'Brazil', - 'canada': 'Canada', - 'european union': 'European Union', - 'eu': 'European Union', - 'e.u.': 'European Union', - 'france': 'France', - 'mexico': 'Mexico', - 'méxico': 'Mexico', - 'méjico': 'Mexico', - 'spain': 'Spain', - 'espana': 'Spain', - 'españa': 'Spain', - 'uk': 'United Kingdom', - 'u.k.': 'United Kingdom', - 'united kingdom': 'United Kingdom', - 'united states of america': 'United States', - 'united states': 'United States', - 'us': 'United States', - 'usa': 'United States', - 'u.s.': 'United States', - 'u.s.a.': 'United States' - } - if country is not None and country.lower() in norm_name: - return REGIONTAGS.get(norm_name.get(country.lower())) - else: - raise ValueError( - 'The available regions are {0}.'.format( - ', '.join('\'{}\''.format(k) for k in REGIONTAGS))) diff --git a/tests/e2e/data/client/test_data_obs_client.py b/tests/e2e/data/client/test_data_obs_client.py deleted file mode 100644 index ebe50806b..000000000 --- a/tests/e2e/data/client/test_data_obs_client.py +++ /dev/null @@ -1,417 +0,0 @@ -# -*- coding: utf-8 -*- - -"""Unit tests for cartoframes.client.DataObsClient""" - -import os -import sys -import json -import pytest -import unittest -import warnings -import pandas as pd - -from carto.exceptions import CartoException - -from cartoframes import read_carto, delete_table -from cartoframes.auth import Credentials -from cartoframes.data.clients import DataObsClient, SQLClient -from cartoframes.data.clients.data_obs_client import get_countrytag -from cartoframes.utils.columns import normalize_name -from tests.e2e.helpers import _UserUrlLoader - -warnings.filterwarnings('ignore') - - -class TestDataObsClientDeprecation(unittest.TestCase, _UserUrlLoader): - def setUp(self): - self.credentials = Credentials(None, None, self.user_url().format(username=None)) - - def test_class_deprecation(self): - with warnings.catch_warnings(record=True) as w: - _ = DataObsClient(self.credentials) - assert issubclass(w[-1].category, DeprecationWarning) - assert 'deprecated' in str(w[-1].message) - - def test_boundaries_deprecation(self): - with warnings.catch_warnings(record=True) as w: - do = DataObsClient(self.credentials) - - with warnings.catch_warnings(record=True) as w: - try: - do.boundaries() - except Exception: - pass - - assert issubclass(w[-1].category, DeprecationWarning) - assert 'deprecated' in str(w[-1].message) - - def test_discovery_deprecation(self): - with warnings.catch_warnings(record=True) as w: - do = DataObsClient(self.credentials) - - with warnings.catch_warnings(record=True) as w: - try: - do.discovery() - except Exception: - pass - - assert issubclass(w[-1].category, DeprecationWarning) - assert 'deprecated' in str(w[-1].message) - - def test_augment_deprecation(self): - with warnings.catch_warnings(record=True) as w: - do = DataObsClient(self.credentials) - - with warnings.catch_warnings(record=True) as w: - try: - do.augment() - except Exception: - pass - - assert issubclass(w[-1].category, DeprecationWarning) - assert 'deprecated' in str(w[-1].message) - - -@pytest.mark.skip() -class TestDataObsClient(unittest.TestCase, _UserUrlLoader): - """Tests for cartoframes.client.DataObsClient""" - - def setUp(self): - if (os.environ.get('APIKEY') is None or - os.environ.get('USERNAME') is None): - try: - creds = json.loads(open('tests/e2e/secret.json').read()) - self.apikey = creds['APIKEY'] - self.username = creds['USERNAME'] - except Exception: - warnings.warn("Skipping Context tests. To test it, " - "create a `secret.json` file in test/ by " - "renaming `secret.json.sample` to `secret.json` " - "and updating the credentials to match your " - "environment.") - self.apikey = None - self.username = None - else: - self.apikey = os.environ['APIKEY'] - self.username = os.environ['USERNAME'] - - self.base_url = self.user_url().format(username=self.username) - self.credentials = Credentials(self.username, self.apikey, self.base_url) - self.sql_client = SQLClient(self.credentials) - - # table naming info - has_mpl = 'mpl' if os.environ.get('MPLBACKEND') else 'nonmpl' - pyver = sys.version[0:3].replace('.', '_') - buildnum = os.environ.get('TRAVIS_BUILD_NUMBER') - - test_slug = '{ver}_{num}_{mpl}'.format( - ver=pyver, num=buildnum, mpl=has_mpl - ) - - # test tables - self.test_read_table = 'cb_2013_us_csa_500k' - self.valid_columns = set(['affgeoid', 'aland', 'awater', 'created_at', - 'csafp', 'geoid', 'lsad', 'name', 'the_geom', - 'updated_at']) - # torque table - self.test_point_table = 'tweets_obama' - - # for writing to carto - self.test_write_table = normalize_name( - 'cf_test_table_{}'.format(test_slug) - ) - - self.mixed_case_table = normalize_name( - 'AbCdEfG_{}'.format(test_slug) - ) - - # for batch writing to carto - self.test_write_batch_table = normalize_name( - 'cf_testbatch_table_{}'.format(test_slug) - ) - - self.test_write_lnglat_table = normalize_name( - 'cf_testwrite_lnglat_table_{}'.format(test_slug) - ) - - self.write_named_index = normalize_name( - 'cf_testwrite_non_default_index_{}'.format(test_slug) - ) - - # for queries - self.test_query_table = normalize_name( - 'cf_testquery_table_{}'.format(test_slug) - ) - - self.test_delete_table = normalize_name( - 'cf_testdelete_table_{}'.format(test_slug) - ) - - # for data observatory - self.test_data_table = 'carto_usa_offices' - - def tearDown(self): - """restore to original state""" - tables = (self.test_write_table, - self.test_write_batch_table, - self.test_write_lnglat_table, - self.test_query_table, - self.mixed_case_table.lower(), - self.write_named_index, ) - sql_drop = 'DROP TABLE IF EXISTS {};' - - for table in tables: - try: - delete_table(table, credentials=self.credentials) - self.sql_client.query(sql_drop.format(table)) - except CartoException: - warnings.warn('Error deleting tables') - - def test_boundaries(self): - """DataObsClient.boundaries""" - do = DataObsClient(self.credentials) - - # all boundary metadata - boundary_meta = do.boundaries() - self.assertTrue(boundary_meta.shape[0] > 0, - msg='has non-zero number of boundaries') - meta_cols = set(('geom_id', 'geom_tags', 'geom_type', )) - self.assertTrue(meta_cols & set(boundary_meta.columns)) - - # boundary metadata with correct timespan - meta_2015 = do.boundaries(timespan='2015') - self.assertTrue(meta_2015[meta_2015.valid_timespan].shape[0] > 0) - - # test for no data with an incorrect or invalid timespan - meta_9999 = do.boundaries(timespan='invalid_timespan') - self.assertTrue(meta_9999[meta_9999.valid_timespan].shape[0] == 0) - - # boundary metadata in a region - regions = ( - self.test_read_table, - self.test_data_table, - [5.9559111595, 45.8179931641, 10.4920501709, 47.808380127], - 'Australia', ) - for region in regions: - boundary_meta = do.boundaries(region=region) - self.assertTrue(meta_cols & set(boundary_meta.columns)) - self.assertTrue(boundary_meta.shape[0] > 0, - msg='has non-zero number of boundaries') - - # boundaries for world - boundaries = do.boundaries(boundary='us.census.tiger.state') - self.assertTrue(boundaries.shape[0] > 0) - self.assertEqual(boundaries.shape[1], 2) - self.assertSetEqual(set(('the_geom', 'geom_refs', )), - set(boundaries.columns)) - - # boundaries for region - boundaries = ('us.census.tiger.state', ) - for b in boundaries: - geoms = do.boundaries( - boundary=b, - region=self.test_data_table) - self.assertTrue(geoms.shape[0] > 0) - self.assertEqual(geoms.shape[1], 2) - self.assertSetEqual(set(('the_geom', 'geom_refs', )), - set(geoms.columns)) - - # presence or lack of clipped boundaries - nonclipped = (True, False, ) - for tf in nonclipped: - meta = do.boundaries(include_nonclipped=tf) - self.assertEqual( - 'us.census.tiger.state' in set(meta.geom_id), - tf - ) - - with self.assertRaises(ValueError): - do.boundaries(region=[1, 2, 3]) - - with self.assertRaises(ValueError): - do.boundaries(region=10) - - def test_discovery(self): - """DataObsClient.discovery""" - do = DataObsClient(self.credentials) - - meta = do.discovery(self.test_read_table, - keywords=('poverty', ), - time=('2010 - 2014', )) - meta_columns = set(( - 'denom_aggregate', 'denom_colname', 'denom_description', - 'denom_geomref_colname', 'denom_id', 'denom_name', - 'denom_reltype', 'denom_t_description', 'denom_tablename', - 'denom_type', 'geom_colname', 'geom_description', - 'geom_geomref_colname', 'geom_id', 'geom_name', - 'geom_t_description', 'geom_tablename', 'geom_timespan', - 'geom_type', 'id', 'max_score_rank', 'max_timespan_rank', - 'normalization', 'num_geoms', 'numer_aggregate', - 'numer_colname', 'numer_description', 'numer_geomref_colname', - 'numer_id', 'numer_name', 'numer_t_description', - 'numer_tablename', 'numer_timespan', 'numer_type', 'score', - 'score_rank', 'score_rownum', 'suggested_name', 'target_area', - 'target_geoms', 'timespan_rank', 'timespan_rownum')) - self.assertSetEqual(set(meta.columns), meta_columns, - msg='metadata columns are all there') - self.assertTrue((meta['numer_timespan'] == '2010 - 2014').all()) - self.assertTrue((meta['numer_description'].str.contains('poverty')).all()) - - # test region = list of lng/lats - with self.assertRaises(ValueError): - do.discovery([1, 2, 3]) - - switzerland = [5.9559111595, 45.8179931641, - 10.4920501709, 47.808380127] - dd = do.discovery(switzerland, keywords='freight', time='2010') - self.assertEqual(dd['numer_id'][0], 'eu.eurostat.tgs00078') - - dd = do.discovery('Australia', - regex='.*Torres Strait Islander.*') - for nid in dd['numer_id'].values: - self.assertRegexpMatches(nid, r'^au\.data\.B01_Indig_[A-Za-z_]+Torres_St[A-Za-z_]+[FMP]$') - - with self.assertRaises(CartoException): - do.discovery('non_existent_table_abcdefg') - - dd = do.discovery('United States', - boundaries='us.epa.huc.hydro_unit', - time=('2006', '2010', )) - self.assertTrue(dd.shape[0] >= 1) - - poverty = do.discovery( - 'United States', - boundaries='us.census.tiger.census_tract', - keywords=['poverty status', ], - time='2011 - 2015', - include_quantiles=False) - df_quantiles = poverty[poverty.numer_aggregate == 'quantile'] - self.assertEqual(df_quantiles.shape[0], 0) - - poverty = do.discovery( - 'United States', - boundaries='us.census.tiger.census_tract', - keywords=['poverty status', ], - time='2011 - 2015', - include_quantiles=True) - df_quantiles = poverty[poverty.numer_aggregate == 'quantile'] - self.assertTrue(df_quantiles.shape[0] > 0) - - def test_augment(self): - """DataObsClient.augment""" - do = DataObsClient(self.credentials) - - meta = do.discovery(self.test_read_table, - keywords=('poverty', ), - time=('2010 - 2014', )) - gdf = do.augment(self.test_data_table, meta) - anscols = set(meta['suggested_name']) - origcols = set( - read_carto(self.test_data_table, credentials=self.credentials, limit=1, decode_geom=True).columns) - self.assertSetEqual(anscols, set(gdf.columns) - origcols - {'the_geom', 'cartodb_id'}) - - meta = [{'numer_id': 'us.census.acs.B19013001', - 'geom_id': 'us.census.tiger.block_group', - 'numer_timespan': '2011 - 2015'}, ] - gdf = do.augment(self.test_data_table, meta) - self.assertSetEqual(set(('median_income_2011_2015', )), - set(gdf.columns) - origcols - {'the_geom', 'cartodb_id'}) - - with self.assertRaises(ValueError, msg='no measures'): - meta = do.discovery('United States', keywords='not a measure') - do.augment(self.test_read_table, meta) - - with self.assertRaises(ValueError, msg='too many metadata measures'): - # returns ~180 measures - meta = do.discovery(region='united states', - keywords='education') - do.augment(self.test_read_table, meta) - - @pytest.mark.skip() - def test_augment_with_persist_as(self): - """DataObsClient.augment with persist_as""" - do = DataObsClient(self.credentials) - - meta = do.discovery(self.test_read_table, - keywords=('poverty', ), - time=('2010 - 2014', )) - gdf = do.augment(self.test_data_table, meta) - anscols = set(meta['suggested_name']) - origcols = set( - read_carto(self.test_data_table, credentials=self.credentials, limit=1, decode_geom=True).columns) - self.assertSetEqual(anscols, set(gdf.columns) - origcols - {'the_geom', 'cartodb_id'}) - - meta = [{'numer_id': 'us.census.acs.B19013001', - 'geom_id': 'us.census.tiger.block_group', - 'numer_timespan': '2011 - 2015'}, ] - gdf = do.augment(self.test_data_table, meta, persist_as=self.test_write_table) - self.assertSetEqual(set(('median_income_2011_2015', )), - set(gdf.columns) - origcols - {'the_geom', 'cartodb_id'}) - self.assertEqual(gdf.index.name, 'cartodb_id') - self.assertEqual(gdf.index.dtype, 'int64') - - df = read_carto(self.test_write_table, credentials=self.credentials, decode_geom=False) - - self.assertEqual(df.index.name, 'cartodb_id') - self.assertEqual(df.index.dtype, 'int64') - - # same number of rows - self.assertEqual(len(df), len(gdf), - msg='Expected number or rows') - - # same type of object - self.assertIsInstance(df, pd.DataFrame, - 'Should be a pandas DataFrame') - # same column names - self.assertSetEqual(set(gdf.columns.values), - set(df.columns.values), - msg='Should have the columns requested') - - # should have exected schema - self.assertEqual( - sorted(tuple(str(d) for d in df.dtypes)), - sorted(tuple(str(d) for d in gdf.dtypes)), - msg='Should have same schema/types' - ) - - def test_augment_column_name_collision(self): - """DataObsClient.augment column name collision""" - dup_col = 'female_third_level_studies_2011_by_female_pop' - self.sql_client.query( - """ - create table {table} as ( - select cdb_latlng(40.4165,-3.70256) the_geom, - 1 {dup_col}) - """.format( - dup_col=dup_col, - table=self.test_write_table - ) - ) - self.sql_client.query( - "select cdb_cartodbfytable('public', '{table}')".format( - table=self.test_write_table - ) - ) - - do = DataObsClient(self.credentials) - meta = do.discovery(region=self.test_write_table, keywords='female') - meta = meta[meta.suggested_name == dup_col] - gdf = do.augment( - self.test_write_table, - meta[meta.suggested_name == dup_col] - ) - - self.assertIn('_' + dup_col, gdf.keys()) - - def test_get_countrytag(self): - valid_regions = ('Australia', 'Brasil', 'EU', 'España', 'U.K.', ) - valid_answers = ['section/tags.{c}'.format(c=c) - for c in ('au', 'br', 'eu', 'spain', 'uk', )] - invalid_regions = ('USofA', None, '', 'Jupiter', ) - - for idx, r in enumerate(valid_regions): - self.assertEqual(get_countrytag(r.lower()), valid_answers[idx]) - - for r in invalid_regions: - with self.assertRaises(ValueError): - get_countrytag(r) From fb7c2812e408b8083176f5f37d77a14afd8d2bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Tue, 9 Mar 2021 09:25:28 +0100 Subject: [PATCH 04/26] Point to PR number --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67f35b9a5..68e6c4c50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [NEXT] - 2021-X-X ### Removed -- Remove DataObsClient (#) +- Remove DataObsClient (#1721) ## [1.1.1] - 2021-02-12 From 274eff5550e8b2ef879b165a4bfeb446e2edd436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Tue, 9 Mar 2021 14:20:44 +0100 Subject: [PATCH 05/26] Remove ref title --- docs/reference/introduction.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/reference/introduction.rst b/docs/reference/introduction.rst index 43f9fdd82..8a68aae47 100644 --- a/docs/reference/introduction.rst +++ b/docs/reference/introduction.rst @@ -1,6 +1,3 @@ -CARTOframes API Reference -========================= - Introduction ------------ From a5c48adfa71fea516517e43b3fd7525337b0d404 Mon Sep 17 00:00:00 2001 From: Mmoncadaisla Date: Wed, 10 Mar 2021 10:44:23 +0100 Subject: [PATCH 06/26] Avoid renaming geometry if geometry name is already GEOM_COLUMN_NAME (the_geom) --- cartoframes/io/carto.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cartoframes/io/carto.py b/cartoframes/io/carto.py index 51e510921..6a42101c0 100644 --- a/cartoframes/io/carto.py +++ b/cartoframes/io/carto.py @@ -156,7 +156,8 @@ def to_carto(dataframe, table_name, credentials=None, if_exists='fail', geom_col gdf.drop(columns=[GEOM_COLUMN_NAME], inplace=True) # Prepare geometry column for the upload - gdf.rename_geometry(GEOM_COLUMN_NAME, inplace=True) + if dataframe.geometry.name != GEOM_COLUMN_NAME: + gdf.rename_geometry(GEOM_COLUMN_NAME, inplace=True) elif isinstance(dataframe, GeoDataFrame): log.warning('Geometry column not found in the GeoDataFrame.') From 7af1e3caa8c8124537604c614778dac1e04adc1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Wed, 10 Mar 2021 15:56:06 +0100 Subject: [PATCH 07/26] Add autoformat in dataset.describe --- .../data/observatory/catalog/dataset.py | 19 +++++++++-- .../unit/data/observatory/catalog/examples.py | 2 +- .../data/observatory/catalog/test_dataset.py | 34 ++++++++++++++++++- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/cartoframes/data/observatory/catalog/dataset.py b/cartoframes/data/observatory/catalog/dataset.py index ecbf714b7..533793feb 100644 --- a/cartoframes/data/observatory/catalog/dataset.py +++ b/cartoframes/data/observatory/catalog/dataset.py @@ -293,11 +293,14 @@ def geom_coverage(self): """ return geom_coverage(self.geography) - def describe(self): + def describe(self, autoformat=True): """Shows a summary of the actual stats of the variables (columns) of the dataset. Some of the stats provided per variable are: avg, max, min, sum, range, stdev, q1, q3, median and interquartile_range + Args: + autoformat (boolean): set automatic format for values. Default is True. + Returns: pandas.DataFrame @@ -317,7 +320,19 @@ def describe(self): # interquartile_range """ - return dataset_describe(self.variables) + + FLOAT_FORMAT = 'display.float_format' + + if autoformat: + current_format = pd.get_option(FLOAT_FORMAT) + pd.set_option(FLOAT_FORMAT, lambda x: '%.3f' % x) + + output = dataset_describe(self.variables) + + if autoformat: + pd.set_option(FLOAT_FORMAT, current_format) + + return output @classmethod @check_do_enabled diff --git a/tests/unit/data/observatory/catalog/examples.py b/tests/unit/data/observatory/catalog/examples.py index 36737cae9..7730cd3fa 100644 --- a/tests/unit/data/observatory/catalog/examples.py +++ b/tests/unit/data/observatory/catalog/examples.py @@ -147,7 +147,7 @@ 'dataset_id': 'dataset1', 'agg_method': '', 'variable_group_id': 'vargroup1', - 'summary_json': [{'key': 'value'}] + 'summary_json': {'key': 'value', 'stats': {'v': 1.23456789}, 'quantiles': {}} } test_variable1 = Variable(db_variable1) test_variable2 = Variable(db_variable2) diff --git a/tests/unit/data/observatory/catalog/test_dataset.py b/tests/unit/data/observatory/catalog/test_dataset.py index 9d3b519e6..bbc4942ea 100644 --- a/tests/unit/data/observatory/catalog/test_dataset.py +++ b/tests/unit/data/observatory/catalog/test_dataset.py @@ -3,7 +3,7 @@ import pytest import pandas as pd -from unittest.mock import patch +from unittest.mock import patch, call, ANY from pyrestcli.exceptions import ServerErrorException from cartoframes.auth import Credentials @@ -199,6 +199,38 @@ def test_summary_fields_by_type(self): # Then assert isinstance(summary, pd.Series) + @patch.object(pd, 'get_option') + @patch.object(pd, 'set_option') + @patch.object(VariableRepository, 'get_all') + def test_summary_describe(self, mocked_repo, mocked_set, mocked_get): + # Given + mocked_get.return_value = 'current_format' + dataset = Dataset(db_dataset2) + + # When + summary = dataset.describe() + + # Then + assert isinstance(summary, pd.DataFrame) + mocked_get.assert_called_once_with('display.float_format') + mocked_set.assert_has_calls([ + call('display.float_format', ANY), + call('display.float_format', 'current_format') + ]) + + @patch.object(pd, 'set_option') + @patch.object(VariableRepository, 'get_all') + def test_summary_describe_custom_format(self, mocked_repo, mocked_set): + # Given + dataset = Dataset(db_dataset2) + + # When + summary = dataset.describe(autoformat=False) + + # Then + assert isinstance(summary, pd.DataFrame) + mocked_set.assert_not_called() + @patch.object(DatasetRepository, 'get_all') def test_get_all_datasets(self, mocked_repo): # Given From 06fe38307ba08d7129592c96f897e7218681f9ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Wed, 10 Mar 2021 16:03:40 +0100 Subject: [PATCH 08/26] Add autoformat in variable.describe --- .../data/observatory/catalog/dataset.py | 1 - .../data/observatory/catalog/variable.py | 20 ++++++++++-- .../data/observatory/catalog/test_variable.py | 32 ++++++++++++++++++- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/cartoframes/data/observatory/catalog/dataset.py b/cartoframes/data/observatory/catalog/dataset.py index 533793feb..4a888d389 100644 --- a/cartoframes/data/observatory/catalog/dataset.py +++ b/cartoframes/data/observatory/catalog/dataset.py @@ -320,7 +320,6 @@ def describe(self, autoformat=True): # interquartile_range """ - FLOAT_FORMAT = 'display.float_format' if autoformat: diff --git a/cartoframes/data/observatory/catalog/variable.py b/cartoframes/data/observatory/catalog/variable.py index 6ac9db55f..42c644afc 100644 --- a/cartoframes/data/observatory/catalog/variable.py +++ b/cartoframes/data/observatory/catalog/variable.py @@ -1,3 +1,5 @@ +import pandas as pd + from .entity import CatalogEntity from .repository.dataset_repo import get_dataset_repo from .repository.variable_repo import get_variable_repo @@ -101,11 +103,14 @@ def dataset_name(self): _, _, dataset, _ = self.id.split('.') return dataset - def describe(self): + def describe(self, autoformat=True): """Shows a summary of the actual stats of the variable (column) of the dataset. Some of the stats provided per variable are: avg, max, min, sum, range, stdev, q1, q3, median and interquartile_range + Args: + autoformat (boolean): set automatic format for values. Default is True. + Example: .. code:: @@ -122,8 +127,19 @@ def describe(self): # interquartile_range """ + FLOAT_FORMAT = 'display.float_format' + + if autoformat: + current_format = pd.get_option(FLOAT_FORMAT) + pd.set_option(FLOAT_FORMAT, lambda x: '%.3f' % x) + data = self.data['summary_json'] - return variable_describe(data) + output = variable_describe(data) + + if autoformat: + pd.set_option(FLOAT_FORMAT, current_format) + + return output def head(self): """Returns a sample of the 10 first values of the variable data. diff --git a/tests/unit/data/observatory/catalog/test_variable.py b/tests/unit/data/observatory/catalog/test_variable.py index a51ae7e19..74d6c5de5 100644 --- a/tests/unit/data/observatory/catalog/test_variable.py +++ b/tests/unit/data/observatory/catalog/test_variable.py @@ -1,6 +1,6 @@ import pandas as pd -from unittest.mock import patch +from unittest.mock import patch, call, ANY from cartoframes.data.observatory.catalog.entity import CatalogList from cartoframes.data.observatory.catalog.variable import Variable @@ -176,3 +176,33 @@ def test_variables_are_exported_as_dataframe(self): assert isinstance(variable_df, pd.DataFrame) assert isinstance(sliced_variable, pd.Series) assert sliced_variable.equals(expected_variable_df) + + @patch.object(pd, 'get_option') + @patch.object(pd, 'set_option') + @patch.object(VariableRepository, 'get_all') + def test_summary_describe(self, mocked_repo, mocked_set, mocked_get): + # Given + mocked_get.return_value = 'current_format' + variable = test_variables[0] + + # When + summary = variable.describe() + + # Then + mocked_get.assert_called_once_with('display.float_format') + mocked_set.assert_has_calls([ + call('display.float_format', ANY), + call('display.float_format', 'current_format') + ]) + + @patch.object(pd, 'set_option') + @patch.object(VariableRepository, 'get_all') + def test_summary_describe_custom_format(self, mocked_repo, mocked_set): + # Given + variable = test_variables[0] + + # When + summary = variable.describe(autoformat=False) + + # Then + mocked_set.assert_not_called() \ No newline at end of file From 5c2565f38b514555781adf3a619e6ae1091e4130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Wed, 10 Mar 2021 16:10:07 +0100 Subject: [PATCH 09/26] Fix linter --- tests/unit/data/observatory/catalog/test_variable.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/data/observatory/catalog/test_variable.py b/tests/unit/data/observatory/catalog/test_variable.py index 74d6c5de5..2b453dcc5 100644 --- a/tests/unit/data/observatory/catalog/test_variable.py +++ b/tests/unit/data/observatory/catalog/test_variable.py @@ -176,7 +176,7 @@ def test_variables_are_exported_as_dataframe(self): assert isinstance(variable_df, pd.DataFrame) assert isinstance(sliced_variable, pd.Series) assert sliced_variable.equals(expected_variable_df) - + @patch.object(pd, 'get_option') @patch.object(pd, 'set_option') @patch.object(VariableRepository, 'get_all') @@ -186,7 +186,7 @@ def test_summary_describe(self, mocked_repo, mocked_set, mocked_get): variable = test_variables[0] # When - summary = variable.describe() + variable.describe() # Then mocked_get.assert_called_once_with('display.float_format') @@ -202,7 +202,7 @@ def test_summary_describe_custom_format(self, mocked_repo, mocked_set): variable = test_variables[0] # When - summary = variable.describe(autoformat=False) + variable.describe(autoformat=False) # Then - mocked_set.assert_not_called() \ No newline at end of file + mocked_set.assert_not_called() From e9fde020c6026c258f03cd319b514ae8df7e3056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Wed, 10 Mar 2021 17:31:52 +0100 Subject: [PATCH 10/26] Filter product datasets/geographies with metadata entities endpoint --- .../data/observatory/catalog/repository/dataset_repo.py | 1 + .../data/observatory/catalog/repository/geography_repo.py | 1 + .../data/observatory/catalog/repository/repo_client.py | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/cartoframes/data/observatory/catalog/repository/dataset_repo.py b/cartoframes/data/observatory/catalog/repository/dataset_repo.py index 4bd26adec..cc9f906a6 100644 --- a/cartoframes/data/observatory/catalog/repository/dataset_repo.py +++ b/cartoframes/data/observatory/catalog/repository/dataset_repo.py @@ -25,6 +25,7 @@ def get_all(self, filters=None, credentials=None): # Using user credentials to fetch entities self.client.set_user_credentials(credentials) + filters = self.client.get_entities_filters(filters) entities = self._get_filtered_entities(filters) self.client.reset_user_credentials() return entities diff --git a/cartoframes/data/observatory/catalog/repository/geography_repo.py b/cartoframes/data/observatory/catalog/repository/geography_repo.py index d23fc9227..19d8f6524 100644 --- a/cartoframes/data/observatory/catalog/repository/geography_repo.py +++ b/cartoframes/data/observatory/catalog/repository/geography_repo.py @@ -28,6 +28,7 @@ def get_all(self, filters=None, credentials=None): # Using user credentials to fetch entities self.client.set_user_credentials(credentials) + filters = self.client.get_entities_filters(filters) entities = self._get_filtered_entities(filters) self.client.reset_user_credentials() return entities diff --git a/cartoframes/data/observatory/catalog/repository/repo_client.py b/cartoframes/data/observatory/catalog/repository/repo_client.py index b828b4c91..6ef42d99d 100644 --- a/cartoframes/data/observatory/catalog/repository/repo_client.py +++ b/cartoframes/data/observatory/catalog/repository/repo_client.py @@ -73,6 +73,13 @@ def get_variables_groups(self, filters=None): entity = 'datasets/{0}/variables_groups'.format(filters.pop('dataset')) return self._fetch_entity(entity, filters) + def get_entities_filters(self, filters=None): + self.set_external_credentials() + if filters is not None: + filters['filter_catalog'] = False + entities = self._fetch_entity('entities', filters) + return {'id': [result['id'] for result in entities['results']]} + def _get_filter_id(self, filters, use_slug=False): if isinstance(filters, dict): filter_id = filters.get('id') From bfaaf08327f3d4a058bce4a1c2d091dc2a33febf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Wed, 10 Mar 2021 17:31:57 +0100 Subject: [PATCH 11/26] Update tests --- .../catalog/repository/test_dataset_repo.py | 44 ++++++++++++----- .../catalog/repository/test_geography_repo.py | 48 ++++++++++++++----- 2 files changed, 69 insertions(+), 23 deletions(-) diff --git a/tests/unit/data/observatory/catalog/repository/test_dataset_repo.py b/tests/unit/data/observatory/catalog/repository/test_dataset_repo.py index 20471a215..cc92d7423 100644 --- a/tests/unit/data/observatory/catalog/repository/test_dataset_repo.py +++ b/tests/unit/data/observatory/catalog/repository/test_dataset_repo.py @@ -18,9 +18,11 @@ class TestDatasetRepo(object): @patch.object(RepoClient, 'get_datasets') - def test_get_all(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_all(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] + mocked_filters.side_effect = lambda f: f repo = DatasetRepository() # When @@ -32,10 +34,12 @@ def test_get_all(self, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') + @patch.object(RepoClient, 'get_entities_filters') @patch('cartoframes.data.observatory.catalog.repository.entity_repo.get_subscription_ids') - def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_get_datasets): + def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_filters, mocked_get_datasets): # Given mocked_get_subscription_ids.return_value = [db_dataset1['id'], db_dataset2['id']] + mocked_filters.side_effect = lambda f: f mocked_get_datasets.return_value = [db_dataset1, db_dataset2] credentials = Credentials('user', '1234') repo = DatasetRepository() @@ -49,9 +53,11 @@ def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_get_datas assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - def test_get_all_when_empty(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_all_when_empty(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [] + mocked_filters.side_effect = lambda f: f repo = DatasetRepository() # When @@ -62,9 +68,11 @@ def test_get_all_when_empty(self, mocked_repo): assert datasets == [] @patch.object(RepoClient, 'get_datasets') - def test_get_all_only_uses_allowed_filters(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_all_only_uses_allowed_filters(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] + mocked_filters.side_effect = lambda f: f repo = DatasetRepository() filters = { COUNTRY_FILTER: 'usa', @@ -90,9 +98,11 @@ def test_get_all_only_uses_allowed_filters(self, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - def test_get_by_id(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_by_id(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1] + mocked_filters.side_effect = lambda f: f requested_id = db_dataset1['id'] repo = DatasetRepository() @@ -104,9 +114,11 @@ def test_get_by_id(self, mocked_repo): assert dataset == test_dataset1 @patch.object(RepoClient, 'get_datasets') - def test_get_by_id_unknown_fails(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_by_id_unknown_fails(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [] + mocked_filters.side_effect = lambda f: f requested_id = 'unknown_id' repo = DatasetRepository() @@ -115,9 +127,11 @@ def test_get_by_id_unknown_fails(self, mocked_repo): repo.get_by_id(requested_id) @patch.object(RepoClient, 'get_datasets') - def test_get_by_slug(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_by_slug(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1] + mocked_filters.side_effect = lambda f: f requested_slug = db_dataset1['slug'] repo = DatasetRepository() @@ -129,9 +143,11 @@ def test_get_by_slug(self, mocked_repo): assert dataset == test_dataset1 @patch.object(RepoClient, 'get_datasets') - def test_get_by_id_list(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_by_id_list(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] + mocked_filters.side_effect = lambda f: f repo = DatasetRepository() # When @@ -143,9 +159,11 @@ def test_get_by_id_list(self, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - def test_get_by_slug_list(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_by_slug_list(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] + mocked_filters.side_effect = lambda f: f repo = DatasetRepository() # When @@ -157,9 +175,11 @@ def test_get_by_slug_list(self, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - def test_get_by_slug_and_id_list(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_by_slug_and_id_list(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] + mocked_filters.side_effect = lambda f: f repo = DatasetRepository() # When @@ -171,9 +191,11 @@ def test_get_by_slug_and_id_list(self, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - def test_missing_fields_are_mapped_as_None(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_missing_fields_are_mapped_as_None(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [{'id': 'dataset1'}] + mocked_filters.side_effect = lambda f: f repo = DatasetRepository() expected_datasets = CatalogList([Dataset({ diff --git a/tests/unit/data/observatory/catalog/repository/test_geography_repo.py b/tests/unit/data/observatory/catalog/repository/test_geography_repo.py index 5a1ed0011..2a4efc612 100644 --- a/tests/unit/data/observatory/catalog/repository/test_geography_repo.py +++ b/tests/unit/data/observatory/catalog/repository/test_geography_repo.py @@ -18,9 +18,11 @@ class TestGeographyRepo(object): @patch.object(RepoClient, 'get_geographies') - def test_get_all(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_all(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] + mocked_filters.side_effect = lambda f: f repo = GeographyRepository() # When @@ -32,10 +34,12 @@ def test_get_all(self, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') + @patch.object(RepoClient, 'get_entities_filters') @patch('cartoframes.data.observatory.catalog.repository.entity_repo.get_subscription_ids') - def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_get_geographies): + def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_filters, mocked_get_geographies): # Given mocked_get_subscription_ids.return_value = [db_geography1['id'], db_geography2['id']] + mocked_filters.side_effect = lambda f: f mocked_get_geographies.return_value = [db_geography1, db_geography2] credentials = Credentials('user', '1234') repo = GeographyRepository() @@ -49,9 +53,11 @@ def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_get_geogr assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - def test_get_all_when_empty(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_all_when_empty(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [] + mocked_filters.side_effect = lambda f: f repo = GeographyRepository() # When @@ -62,9 +68,11 @@ def test_get_all_when_empty(self, mocked_repo): assert geographies == [] @patch.object(RepoClient, 'get_geographies') - def test_get_all_only_uses_allowed_filters(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_all_only_uses_allowed_filters(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] + mocked_filters.side_effect = lambda f: f repo = GeographyRepository() filters = { COUNTRY_FILTER: 'usa', @@ -89,9 +97,11 @@ def test_get_all_only_uses_allowed_filters(self, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - def test_get_by_id(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_by_id(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1] + mocked_filters.side_effect = lambda f: f requested_id = db_geography1['id'] repo = GeographyRepository() @@ -104,9 +114,11 @@ def test_get_by_id(self, mocked_repo): assert geography == test_geography1 @patch.object(RepoClient, 'get_geographies') - def test_get_by_id_unknown_fails(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_by_id_unknown_fails(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [] + mocked_filters.side_effect = lambda f: f requested_id = 'unknown_id' repo = GeographyRepository() @@ -115,9 +127,11 @@ def test_get_by_id_unknown_fails(self, mocked_repo): repo.get_by_id(requested_id) @patch.object(RepoClient, 'get_geographies') - def test_get_by_slug(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_by_slug(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1] + mocked_filters.side_effect = lambda f: f requested_slug = db_geography1['slug'] repo = GeographyRepository() @@ -129,9 +143,11 @@ def test_get_by_slug(self, mocked_repo): assert geography == test_geography1 @patch.object(RepoClient, 'get_geographies') - def test_get_by_id_list(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_by_id_list(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] + mocked_filters.side_effect = lambda f: f repo = GeographyRepository() # When @@ -143,9 +159,11 @@ def test_get_by_id_list(self, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - def test_get_by_slug_list(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_by_slug_list(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] + mocked_filters.side_effect = lambda f: f repo = GeographyRepository() # When @@ -157,9 +175,11 @@ def test_get_by_slug_list(self, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - def test_get_by_slug_and_id_list(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_by_slug_and_id_list(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] + mocked_filters.side_effect = lambda f: f repo = GeographyRepository() # When @@ -171,9 +191,11 @@ def test_get_by_slug_and_id_list(self, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - def test_get_all_with_join_filters(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_get_all_with_join_filters(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] + mocked_filters.side_effect = lambda f: f repo = GeographyRepository() # When @@ -185,9 +207,11 @@ def test_get_all_with_join_filters(self, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - def test_missing_fields_are_mapped_as_None(self, mocked_repo): + @patch.object(RepoClient, 'get_entities_filters') + def test_missing_fields_are_mapped_as_None(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [{'id': 'geography1'}] + mocked_filters.side_effect = lambda f: f repo = GeographyRepository() expected_geographies = CatalogList([Geography({ From 30e85f0e56ab6290c2ab993c5aaeb473e7796e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Thu, 11 Mar 2021 14:45:49 +0100 Subject: [PATCH 12/26] Review and improve SQLClient utilities --- cartoframes/data/clients/sql_client.py | 100 ++++++++++++++++++------- 1 file changed, 74 insertions(+), 26 deletions(-) diff --git a/cartoframes/data/clients/sql_client.py b/cartoframes/data/clients/sql_client.py index 4b58bd870..3d13ee0e0 100644 --- a/cartoframes/data/clients/sql_client.py +++ b/cartoframes/data/clients/sql_client.py @@ -3,6 +3,7 @@ class SQLClient: """SQLClient class is a client to run SQL queries in a CARTO account. + It also provides basic SQL utilities for analyzing and managing tables. Args: credentials (:py:class:`Credentials `): @@ -11,10 +12,6 @@ class SQLClient: Example: >>> sql = SQLClient(credentials) - >>> sql.query('SELECT * FROM table_name') - >>> sql.execute('DROP TABLE table_name') - >>> sql.distinct('table_name', 'column_name') - >>> sql.count('table_name') """ def __init__(self, credentials=None): @@ -31,6 +28,9 @@ def query(self, query, verbose=False): query (str): SQL query. verbose (bool, optional): flag to return all the response. Default False. + Example: + >>> sql.query('SELECT * FROM table_name') + """ response = self._context_manager.execute_query(query.strip()) if not verbose: @@ -47,6 +47,9 @@ def execute(self, query): Args: query (str): SQL query. + Example: + >>> sql.execute('DROP TABLE table_name') + """ return self._context_manager.execute_long_running_query(query.strip()) @@ -58,6 +61,10 @@ def distinct(self, table_name, column_name): table_name (str): name of the table. column_name (str): name of the column. + Example: + >>> sql.distinct('table_name', 'column_name') + [('value1', 10), ('value2', 5)] + """ query = ''' SELECT {0}, COUNT(*) FROM {1} @@ -72,16 +79,24 @@ def count(self, table_name): Args: table_name (str): name of the table. + Example: + >>> sql.count('table_name') + 15 + """ query = 'SELECT COUNT(*) FROM {};'.format(table_name) output = self.query(query) return output[0].get('count') - def bounds(self, query): + def bounds(self, table_name): """Get the bounds of the geometries in a table. Args: - query (str): SQL query containing a "the_geom" column. + table_name (str): name of the table containing a "the_geom" column. + + Example: + >>> sql.bounds('table_name') + [[-1,-1], [1,1]] """ query = ''' @@ -90,9 +105,9 @@ def bounds(self, query): ARRAY[st_xmax(geom_env), st_ymax(geom_env)] ] bounds FROM ( SELECT ST_Extent(the_geom) geom_env - FROM ({}) q + FROM (SELECT the_geom FROM {}) q ) q; - '''.format(query) + '''.format(table_name) output = self.query(query) return output[0].get('bounds') @@ -104,6 +119,16 @@ def schema(self, table_name, raw=False): raw (bool, optional): return raw dict data if set to True. Default False. + Example: + >>> sql.schema('table_name') + Column name Column type + ------------------------------------- + cartodb_id number + the_geom geometry + the_geom_webmercator geometry + column1 string + column2 number + """ query = 'SELECT * FROM {0} LIMIT 0;'.format(table_name) output = self.query(query, verbose=True) @@ -125,6 +150,14 @@ def describe(self, table_name, column_name): table_name (str): name of the table. column_name (str): name of the column. + Example: + >>> sql.schema('table_name', 'column_name') + count 1.00e+03 + avg 2.00e+01 + min 0.00e+00 + max 5.00e+01 + type: number + """ column_type = self._get_column_type(table_name, column_name) stats = ['COUNT(*)'] @@ -138,22 +171,26 @@ def describe(self, table_name, column_name): '''.format(','.join(stats), table_name) output = self.query(query, verbose=True) fields = output.get('rows')[0] - rows = [(key, '{:0.2e}'.format(fields[key])) for key in fields] + rows = [(key, '{:0.2e}'.format(fields[key])) for key in fields if fields[key] is not None] self._print_table(rows, padding=[5, 10]) print('type: {}'.format(column_type)) - def create_table(self, table_name, columns, cartodbfy=True): + def create_table(self, table_name, column_names, column_types, cartodbfy=True): """Create a table with a specific table name and columns. Args: table_name (str): name of the table. - column_name (str): name of the column. + column_names (list of str): names of the columns. + column_types (list of str): types of the columns. cartodbfy (bool, optional): convert the table to CARTO format. Default True. More info `here `. + Example: + >>> sql.create_table('table_name', ['column1', 'column2'], ['text', 'integer']) + """ - columns = ','.join(' '.join(x) for x in columns) + columns = [' '.join([name, column_types[i]]) for i, name in enumerate(column_names)] schema = self._context_manager.get_schema() query = ''' BEGIN; @@ -163,30 +200,29 @@ def create_table(self, table_name, columns, cartodbfy=True): COMMIT; '''.format( drop='DROP TABLE IF EXISTS {}'.format(table_name), - create='CREATE TABLE {0} ({1})'.format(table_name, columns), + create='CREATE TABLE {0} ({1})'.format(table_name, ','.join(columns)), cartodbfy='SELECT CDB_CartoDBFyTable(\'{0}\', \'{1}\')'.format( schema, table_name) if cartodbfy else '' ) - return self.execute(query) + self.execute(query) def insert_table(self, table_name, column_names, column_values): """Insert a row to the table. Args: table_name (str): name of the table. - column_names (str, list of str): names of the columns. - column_values (str, list of str): values of the columns. + column_names (list of str): names of the columns. + column_values (list of tuple): values of the columns. + + Example: + >>> sql.insert_table('table_name', ['column1', 'column2'], [('value1', 1), ('value2', 2)]) """ - if isinstance(column_names, str): - column_names = [column_names] - if isinstance(column_values, str): - column_names = [column_values] - sql_values = [self._sql_format(x) for x in column_values] + sql_values = [self._row_values_format(row_values) for row_values in column_values] query = ''' - INSERT INTO {0} ({1}) VALUES({2}); + INSERT INTO {0} ({1}) VALUES {2}; '''.format(table_name, ','.join(column_names), ','.join(sql_values)) - return self.execute(query) + self.execute(query) def update_table(self, table_name, column_name, column_value, condition): """Update the column's value for the rows that match the condition. @@ -197,12 +233,15 @@ def update_table(self, table_name, column_name, column_value, condition): column_value (str): value of the column. condition (str): "where" condition of the request. + Example: + >>> sql.update_table('table_name', 'column1', 'VALUE1', 'column1=\'value1\'') + """ value = self._sql_format(column_value) query = ''' UPDATE {0} SET {1}={2} WHERE {3}; '''.format(table_name, column_name, value, condition) - return self.execute(query) + self.execute(query) def rename_table(self, table_name, new_table_name): """Rename a table from its table name. @@ -211,9 +250,12 @@ def rename_table(self, table_name, new_table_name): table_name (str): name of the original table. new_table_name (str): name of the new table. + Example: + >>> sql.rename_table('table_name', 'table_name2') + """ query = 'ALTER TABLE {0} RENAME TO {1};'.format(table_name, new_table_name) - return self.execute(query) + self.execute(query) def drop_table(self, table_name): """Remove a table from its table name. @@ -221,9 +263,12 @@ def drop_table(self, table_name): Args: table_name (str): name of the table. + Example: + >>> sql.drop_table('table_name') + """ query = 'DROP TABLE IF EXISTS {0};'.format(table_name) - return self.execute(query) + self.execute(query) def _get_column_type(self, table_name, column_name): query = 'SELECT {0} FROM {1} LIMIT 0;'.format(column_name, table_name) @@ -239,6 +284,9 @@ def _sql_format(self, value): return 'TRUE' if value else 'FALSE' return str(value) + def _row_values_format(self, row_values): + return '({})'.format(','.join([self._sql_format(value) for value in row_values])) + def _print_table(self, rows, columns=None, padding=None): row_format = '' index = 0 From 2d049628cc8909e0b639a21472b5eef1406e423f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Thu, 11 Mar 2021 14:52:00 +0100 Subject: [PATCH 13/26] Update tests --- tests/unit/data/client/test_sql_client.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/unit/data/client/test_sql_client.py b/tests/unit/data/client/test_sql_client.py index b263d9563..241f97803 100644 --- a/tests/unit/data/client/test_sql_client.py +++ b/tests/unit/data/client/test_sql_client.py @@ -128,7 +128,7 @@ def test_count(self, mocker): def test_bounds(self, mocker): """client.SQLClient.bounds""" mock = mocker.patch.object(ContextManager, 'execute_query', return_value=SQL_BOUNDS_RESPONSE) - output = SQLClient(self.credentials).bounds('query') + output = SQLClient(self.credentials).bounds('table_name') assert output == [ [-16.2500006525, 28.0999760122], @@ -140,7 +140,7 @@ def test_bounds(self, mocker): ARRAY[st_xmax(geom_env), st_ymax(geom_env)] ] bounds FROM ( SELECT ST_Extent(the_geom) geom_env - FROM (query) q + FROM (SELECT the_geom FROM table_name) q ) q; '''.strip()) @@ -187,7 +187,7 @@ def test_create_table_no_cartodbfy(self, mocker): mocker.patch.object(ContextManager, 'get_schema') mock = mocker.patch.object(ContextManager, 'execute_long_running_query') SQLClient(self.credentials).create_table( - 'table_name', [('id', 'INT'), ('name', 'TEXT')], cartodbfy=False) + 'table_name', ['id', 'name'], ['INT', 'TEXT'], cartodbfy=False) mock.assert_called_once_with(''' BEGIN; @@ -202,7 +202,7 @@ def test_create_table_cartodbfy_org_user(self, mocker): mocker.patch.object(ContextManager, 'get_schema', return_value='user_name') mock = mocker.patch.object(ContextManager, 'execute_long_running_query') SQLClient(self.credentials).create_table( - 'table_name', [('id', 'INT'), ('name', 'TEXT')]) + 'table_name', ['id', 'name'], ['INT', 'TEXT']) mock.assert_called_once_with(''' BEGIN; @@ -217,7 +217,7 @@ def test_create_table_cartodbfy_public_user(self, mocker): mocker.patch.object(ContextManager, 'get_schema', return_value='public') mock = mocker.patch.object(ContextManager, 'execute_long_running_query') SQLClient(self.credentials).create_table( - 'table_name', [('id', 'INT'), ('name', 'TEXT')]) + 'table_name', ['id', 'name'], ['INT', 'TEXT']) mock.assert_called_once_with(''' BEGIN; @@ -230,10 +230,10 @@ def test_create_table_cartodbfy_public_user(self, mocker): def test_insert_table(self, mocker): """client.SQLClient.insert_table""" mock = mocker.patch.object(ContextManager, 'execute_long_running_query') - SQLClient(self.credentials).insert_table('table_name', ['id', 'name'], [0, 'a']) + SQLClient(self.credentials).insert_table('table_name', ['id', 'name'], [(0, 'a'), (1, 'b')]) mock.assert_called_once_with(''' - INSERT INTO table_name (id,name) VALUES(0,'a'); + INSERT INTO table_name (id,name) VALUES (0,'a'),(1,'b'); '''.strip()) def test_update_table(self, mocker): From b36a1fef9cd824686d00e49828a6ef0112629844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Fri, 12 Mar 2021 09:29:10 +0100 Subject: [PATCH 14/26] Simplify describe autoformat --- cartoframes/data/observatory/catalog/dataset.py | 8 +------- cartoframes/data/observatory/catalog/variable.py | 8 +------- tests/unit/data/observatory/catalog/test_dataset.py | 12 +++--------- tests/unit/data/observatory/catalog/test_variable.py | 12 +++--------- 4 files changed, 8 insertions(+), 32 deletions(-) diff --git a/cartoframes/data/observatory/catalog/dataset.py b/cartoframes/data/observatory/catalog/dataset.py index 4a888d389..908786bee 100644 --- a/cartoframes/data/observatory/catalog/dataset.py +++ b/cartoframes/data/observatory/catalog/dataset.py @@ -323,15 +323,9 @@ def describe(self, autoformat=True): FLOAT_FORMAT = 'display.float_format' if autoformat: - current_format = pd.get_option(FLOAT_FORMAT) pd.set_option(FLOAT_FORMAT, lambda x: '%.3f' % x) - output = dataset_describe(self.variables) - - if autoformat: - pd.set_option(FLOAT_FORMAT, current_format) - - return output + return dataset_describe(self.variables) @classmethod @check_do_enabled diff --git a/cartoframes/data/observatory/catalog/variable.py b/cartoframes/data/observatory/catalog/variable.py index 42c644afc..f7018c4df 100644 --- a/cartoframes/data/observatory/catalog/variable.py +++ b/cartoframes/data/observatory/catalog/variable.py @@ -130,16 +130,10 @@ def describe(self, autoformat=True): FLOAT_FORMAT = 'display.float_format' if autoformat: - current_format = pd.get_option(FLOAT_FORMAT) pd.set_option(FLOAT_FORMAT, lambda x: '%.3f' % x) data = self.data['summary_json'] - output = variable_describe(data) - - if autoformat: - pd.set_option(FLOAT_FORMAT, current_format) - - return output + return variable_describe(data) def head(self): """Returns a sample of the 10 first values of the variable data. diff --git a/tests/unit/data/observatory/catalog/test_dataset.py b/tests/unit/data/observatory/catalog/test_dataset.py index bbc4942ea..46d6f24eb 100644 --- a/tests/unit/data/observatory/catalog/test_dataset.py +++ b/tests/unit/data/observatory/catalog/test_dataset.py @@ -3,7 +3,7 @@ import pytest import pandas as pd -from unittest.mock import patch, call, ANY +from unittest.mock import patch, ANY from pyrestcli.exceptions import ServerErrorException from cartoframes.auth import Credentials @@ -199,12 +199,10 @@ def test_summary_fields_by_type(self): # Then assert isinstance(summary, pd.Series) - @patch.object(pd, 'get_option') @patch.object(pd, 'set_option') @patch.object(VariableRepository, 'get_all') - def test_summary_describe(self, mocked_repo, mocked_set, mocked_get): + def test_summary_describe(self, mocked_repo, mocked_set): # Given - mocked_get.return_value = 'current_format' dataset = Dataset(db_dataset2) # When @@ -212,11 +210,7 @@ def test_summary_describe(self, mocked_repo, mocked_set, mocked_get): # Then assert isinstance(summary, pd.DataFrame) - mocked_get.assert_called_once_with('display.float_format') - mocked_set.assert_has_calls([ - call('display.float_format', ANY), - call('display.float_format', 'current_format') - ]) + mocked_set.assert_called_once_with('display.float_format', ANY) @patch.object(pd, 'set_option') @patch.object(VariableRepository, 'get_all') diff --git a/tests/unit/data/observatory/catalog/test_variable.py b/tests/unit/data/observatory/catalog/test_variable.py index 2b453dcc5..15e5db28c 100644 --- a/tests/unit/data/observatory/catalog/test_variable.py +++ b/tests/unit/data/observatory/catalog/test_variable.py @@ -1,6 +1,6 @@ import pandas as pd -from unittest.mock import patch, call, ANY +from unittest.mock import patch, ANY from cartoframes.data.observatory.catalog.entity import CatalogList from cartoframes.data.observatory.catalog.variable import Variable @@ -177,23 +177,17 @@ def test_variables_are_exported_as_dataframe(self): assert isinstance(sliced_variable, pd.Series) assert sliced_variable.equals(expected_variable_df) - @patch.object(pd, 'get_option') @patch.object(pd, 'set_option') @patch.object(VariableRepository, 'get_all') - def test_summary_describe(self, mocked_repo, mocked_set, mocked_get): + def test_summary_describe(self, mocked_repo, mocked_set): # Given - mocked_get.return_value = 'current_format' variable = test_variables[0] # When variable.describe() # Then - mocked_get.assert_called_once_with('display.float_format') - mocked_set.assert_has_calls([ - call('display.float_format', ANY), - call('display.float_format', 'current_format') - ]) + mocked_set.assert_called_once_with('display.float_format', ANY) @patch.object(pd, 'set_option') @patch.object(VariableRepository, 'get_all') From ba3a6ff9670183f5469398d20970dc07f26d9a88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Fri, 12 Mar 2021 09:30:34 +0100 Subject: [PATCH 15/26] Fix tests warnings --- cartoframes/io/carto.py | 4 ++-- cartoframes/viz/map.py | 2 +- tests/unit/viz/test_source.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cartoframes/io/carto.py b/cartoframes/io/carto.py index 51e510921..dd31522a4 100644 --- a/cartoframes/io/carto.py +++ b/cartoframes/io/carto.py @@ -55,7 +55,7 @@ def read_carto(source, credentials=None, limit=None, retry_times=3, schema=None, df = context_manager.copy_to(source, schema, limit, retry_times) - gdf = GeoDataFrame(df, crs='epsg:4326') + gdf = GeoDataFrame(df) if index_col: if index_col in gdf: @@ -65,7 +65,7 @@ def read_carto(source, credentials=None, limit=None, retry_times=3, schema=None, if decode_geom and GEOM_COLUMN_NAME in gdf: # Decode geometry column - set_geometry(gdf, GEOM_COLUMN_NAME, inplace=True) + set_geometry(gdf, GEOM_COLUMN_NAME, inplace=True, crs='epsg:4326') if null_geom_value is not None: gdf[GEOM_COLUMN_NAME].fillna(null_geom_value, inplace=True) diff --git a/cartoframes/viz/map.py b/cartoframes/viz/map.py index eba469d75..d026d7bfd 100644 --- a/cartoframes/viz/map.py +++ b/cartoframes/viz/map.py @@ -271,7 +271,7 @@ def _get_bounds(bounds, layers): def _init_layers(layers, parent_map): if layers is None: return [] - if not isinstance(layers, collections.Iterable): + if not isinstance(layers, collections.abc.Iterable): layers.reset_ui(parent_map) return [layers] else: diff --git a/tests/unit/viz/test_source.py b/tests/unit/viz/test_source.py index 8aeec39cf..96994d076 100644 --- a/tests/unit/viz/test_source.py +++ b/tests/unit/viz/test_source.py @@ -147,7 +147,7 @@ def test_dates_in_source(self): source = Source(gdf) assert source.datetime_column_names == ['date_column'] - assert source.gdf.dtypes['date_column'] == np.object + assert source.gdf.dtypes['date_column'] == object @pytest.mark.parametrize('features', [ [POINT], From 563e2aad8e13e6574bb50f8f94d617092c0523e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Fri, 12 Mar 2021 16:51:33 +0100 Subject: [PATCH 16/26] Fix user_id in metrics --- cartoframes/auth/credentials.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cartoframes/auth/credentials.py b/cartoframes/auth/credentials.py index ebaf8fc96..928c908af 100644 --- a/cartoframes/auth/credentials.py +++ b/cartoframes/auth/credentials.py @@ -128,8 +128,7 @@ def user_id(self): log.debug('Getting `user_id` for {}'.format(self._username)) try: - user_me = self.me_data() - user_data = user_me.get('user_data') + user_data = self.me_data.get('user_data') if user_data: self._user_id = user_data.get('id') From aa7d3f22833f92160578d6cf58a1eda76094ceab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Tue, 16 Mar 2021 11:36:13 +0100 Subject: [PATCH 17/26] Apply CR --- cartoframes/data/clients/sql_client.py | 38 ++++++++++++++--------- tests/unit/data/client/test_sql_client.py | 12 +++---- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/cartoframes/data/clients/sql_client.py b/cartoframes/data/clients/sql_client.py index 3d13ee0e0..535940c0f 100644 --- a/cartoframes/data/clients/sql_client.py +++ b/cartoframes/data/clients/sql_client.py @@ -1,5 +1,7 @@ from ...io.managers.context_manager import ContextManager +COLLISION_STRATEGIES = ['fail', 'replace'] + class SQLClient: """SQLClient class is a client to run SQL queries in a CARTO account. @@ -133,7 +135,7 @@ def schema(self, table_name, raw=False): query = 'SELECT * FROM {0} LIMIT 0;'.format(table_name) output = self.query(query, verbose=True) fields = output.get('fields') - if raw: + if raw is True: return {key: fields[key]['type'] for key in fields} else: columns = ['Column name', 'Column type'] @@ -151,7 +153,7 @@ def describe(self, table_name, column_name): column_name (str): name of the column. Example: - >>> sql.schema('table_name', 'column_name') + >>> sql.describe('table_name', 'column_name') count 1.00e+03 avg 2.00e+01 min 0.00e+00 @@ -175,22 +177,29 @@ def describe(self, table_name, column_name): self._print_table(rows, padding=[5, 10]) print('type: {}'.format(column_type)) - def create_table(self, table_name, column_names, column_types, cartodbfy=True): + def create_table(self, table_name, columns_types, if_exists='fail', cartodbfy=True): """Create a table with a specific table name and columns. Args: table_name (str): name of the table. - column_names (list of str): names of the columns. - column_types (list of str): types of the columns. + column_types (dict): dictionary with the column names and types. + if_exists (str, optional): collision strategy if the table already exists in CARTO. + Options are 'fail' or 'replace'. Default 'fail'. cartodbfy (bool, optional): convert the table to CARTO format. Default True. More info `here `. Example: - >>> sql.create_table('table_name', ['column1', 'column2'], ['text', 'integer']) + >>> sql.create_table('table_name', {'column1': 'text', 'column2': 'integer'}) """ - columns = [' '.join([name, column_types[i]]) for i, name in enumerate(column_names)] + if not isinstance(columns_types, dict): + raise ValueError('The columns_types parameter should be a dictionary of column names and types.') + + if if_exists not in COLLISION_STRATEGIES: + raise ValueError('Please provide a valid if_exists value among {}'.format(', '.join(COLLISION_STRATEGIES))) + + columns = ['{0} {1}'.format(cname, ctype) for cname, ctype in columns_types.items()] schema = self._context_manager.get_schema() query = ''' BEGIN; @@ -199,29 +208,28 @@ def create_table(self, table_name, column_names, column_types, cartodbfy=True): {cartodbfy}; COMMIT; '''.format( - drop='DROP TABLE IF EXISTS {}'.format(table_name), + drop='DROP TABLE IF EXISTS {}'.format(table_name) if if_exists == 'replace' else '', create='CREATE TABLE {0} ({1})'.format(table_name, ','.join(columns)), cartodbfy='SELECT CDB_CartoDBFyTable(\'{0}\', \'{1}\')'.format( schema, table_name) if cartodbfy else '' ) self.execute(query) - def insert_table(self, table_name, column_names, column_values): + def insert_table(self, table_name, columns_values): """Insert a row to the table. Args: table_name (str): name of the table. - column_names (list of str): names of the columns. - column_values (list of tuple): values of the columns. - + columns_values (dict): dictionary with the column names and values. Example: - >>> sql.insert_table('table_name', ['column1', 'column2'], [('value1', 1), ('value2', 2)]) + >>> sql.insert_table('table_name', {'column1': ['value1', 'value2'], 'column2': [1, 2]}) """ - sql_values = [self._row_values_format(row_values) for row_values in column_values] + cnames = columns_values.keys() + cvalues = [self._row_values_format(v) for v in zip(*columns_values.values())] query = ''' INSERT INTO {0} ({1}) VALUES {2}; - '''.format(table_name, ','.join(column_names), ','.join(sql_values)) + '''.format(table_name, ','.join(cnames), ','.join(cvalues)) self.execute(query) def update_table(self, table_name, column_name, column_value, condition): diff --git a/tests/unit/data/client/test_sql_client.py b/tests/unit/data/client/test_sql_client.py index 241f97803..fca8600e1 100644 --- a/tests/unit/data/client/test_sql_client.py +++ b/tests/unit/data/client/test_sql_client.py @@ -187,11 +187,11 @@ def test_create_table_no_cartodbfy(self, mocker): mocker.patch.object(ContextManager, 'get_schema') mock = mocker.patch.object(ContextManager, 'execute_long_running_query') SQLClient(self.credentials).create_table( - 'table_name', ['id', 'name'], ['INT', 'TEXT'], cartodbfy=False) + 'table_name', {'id': 'INT', 'name': 'TEXT'}, cartodbfy=False) mock.assert_called_once_with(''' BEGIN; - DROP TABLE IF EXISTS table_name; + ; CREATE TABLE table_name (id INT,name TEXT); ; COMMIT; @@ -202,7 +202,7 @@ def test_create_table_cartodbfy_org_user(self, mocker): mocker.patch.object(ContextManager, 'get_schema', return_value='user_name') mock = mocker.patch.object(ContextManager, 'execute_long_running_query') SQLClient(self.credentials).create_table( - 'table_name', ['id', 'name'], ['INT', 'TEXT']) + 'table_name', {'id': 'INT', 'name': 'TEXT'}, if_exists='replace') mock.assert_called_once_with(''' BEGIN; @@ -217,11 +217,11 @@ def test_create_table_cartodbfy_public_user(self, mocker): mocker.patch.object(ContextManager, 'get_schema', return_value='public') mock = mocker.patch.object(ContextManager, 'execute_long_running_query') SQLClient(self.credentials).create_table( - 'table_name', ['id', 'name'], ['INT', 'TEXT']) + 'table_name', {'id': 'INT', 'name': 'TEXT'}, if_exists='fail') mock.assert_called_once_with(''' BEGIN; - DROP TABLE IF EXISTS table_name; + ; CREATE TABLE table_name (id INT,name TEXT); SELECT CDB_CartoDBFyTable('public', 'table_name'); COMMIT; @@ -230,7 +230,7 @@ def test_create_table_cartodbfy_public_user(self, mocker): def test_insert_table(self, mocker): """client.SQLClient.insert_table""" mock = mocker.patch.object(ContextManager, 'execute_long_running_query') - SQLClient(self.credentials).insert_table('table_name', ['id', 'name'], [(0, 'a'), (1, 'b')]) + SQLClient(self.credentials).insert_table('table_name', {'id': [0, 1], 'name': ['a', 'b']}) mock.assert_called_once_with(''' INSERT INTO table_name (id,name) VALUES (0,'a'),(1,'b'); From b54c0ac49e603d619e65ac522798bbcc1c71ceed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Tue, 16 Mar 2021 11:45:05 +0100 Subject: [PATCH 18/26] Remove outdated text from Data Observatory reference --- docs/reference/data_observatory.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/reference/data_observatory.rst b/docs/reference/data_observatory.rst index 18d48e845..4bd020629 100644 --- a/docs/reference/data_observatory.rst +++ b/docs/reference/data_observatory.rst @@ -4,10 +4,6 @@ Data Observatory With CARTOframes it is possible to enrich your data by using our `Data Observatory <#data-observatory>`__ Catalog through the enrichment methods. -**Important:** The new Data Observatory 2.0 is accessible to selected CARTO Enterprise -users in a private beta. We're still open to more beta testers, so if you're interested, -`please get in touch. `__ - .. automodule:: cartoframes.data.observatory :noindex: :members: From 2405e97de399ff7e6e0daeccdd96d19a701c8696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Fri, 26 Mar 2021 07:01:24 +0100 Subject: [PATCH 19/26] Bump version 1.2.0. Update changelog --- CHANGELOG.md | 12 +++++++++++- README.rst | 8 ++++---- binder/requirements.txt | 2 +- cartoframes/_version.py | 2 +- docs/RELEASING.md | 3 --- package.json | 2 +- 6 files changed, 18 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68e6c4c50..d0dae4fd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [NEXT] - 2021-X-X +## [1.2.0] - 2021-03-26 + +### Changed +- Filter only product entities in subscriptions (#1723) +- Dataset describe not in scientific notation (#1722) +- Review and improve SQLClient utilities (#1725) + +### Fixed +- Fix timestamptz read carto (#1720) +- Avoid renaming geometry if geometry name is already GEOM_COLUMN_NAME (#1726) +- Fix user_id in metrics (#1727) ### Removed - Remove DataObsClient (#1721) diff --git a/README.rst b/README.rst index 660cdd5c7..81772b238 100644 --- a/README.rst +++ b/README.rst @@ -4,8 +4,8 @@ CARTOframes .. image:: https://travis-ci.org/CartoDB/cartoframes.svg?branch=develop :target: https://travis-ci.org/CartoDB/cartoframes -.. image:: https://img.shields.io/badge/pypi-v1.1.1-orange - :target: https://pypi.org/project/cartoframes/1.1.1 +.. image:: https://img.shields.io/badge/pypi-v1.2.0-orange + :target: https://pypi.org/project/cartoframes/1.2.0 A Python package for integrating `CARTO `__ maps, analysis, and data services into data science workflows. @@ -14,11 +14,11 @@ Python data analysis workflows often rely on the de facto standards `pandas Date: Fri, 26 Mar 2021 08:33:39 +0100 Subject: [PATCH 20/26] Improve performance in subscriptions --- .../data/observatory/catalog/catalog.py | 6 +---- .../catalog/repository/dataset_repo.py | 1 - .../catalog/repository/geography_repo.py | 1 - .../catalog/repository/repo_client.py | 9 ++------ .../data/observatory/catalog/subscriptions.py | 22 +++++++++++++------ .../catalog/repository/test_dataset_repo.py | 11 ---------- .../catalog/repository/test_geography_repo.py | 12 ---------- 7 files changed, 18 insertions(+), 44 deletions(-) diff --git a/cartoframes/data/observatory/catalog/catalog.py b/cartoframes/data/observatory/catalog/catalog.py index 050b868f5..693df4b58 100644 --- a/cartoframes/data/observatory/catalog/catalog.py +++ b/cartoframes/data/observatory/catalog/catalog.py @@ -286,13 +286,9 @@ def subscriptions(self, credentials=None): CatalogError: if there's a problem when connecting to the catalog or no datasets are found. """ - _no_filters = {} _credentials = get_credentials(credentials) - return Subscriptions( - Dataset.get_all(_no_filters, _credentials), - Geography.get_all(_no_filters, _credentials) - ) + return Subscriptions(_credentials) def datasets_filter(self, filter_dataset): """Get all the datasets in the Catalog filtered diff --git a/cartoframes/data/observatory/catalog/repository/dataset_repo.py b/cartoframes/data/observatory/catalog/repository/dataset_repo.py index cc9f906a6..4bd26adec 100644 --- a/cartoframes/data/observatory/catalog/repository/dataset_repo.py +++ b/cartoframes/data/observatory/catalog/repository/dataset_repo.py @@ -25,7 +25,6 @@ def get_all(self, filters=None, credentials=None): # Using user credentials to fetch entities self.client.set_user_credentials(credentials) - filters = self.client.get_entities_filters(filters) entities = self._get_filtered_entities(filters) self.client.reset_user_credentials() return entities diff --git a/cartoframes/data/observatory/catalog/repository/geography_repo.py b/cartoframes/data/observatory/catalog/repository/geography_repo.py index 19d8f6524..d23fc9227 100644 --- a/cartoframes/data/observatory/catalog/repository/geography_repo.py +++ b/cartoframes/data/observatory/catalog/repository/geography_repo.py @@ -28,7 +28,6 @@ def get_all(self, filters=None, credentials=None): # Using user credentials to fetch entities self.client.set_user_credentials(credentials) - filters = self.client.get_entities_filters(filters) entities = self._get_filtered_entities(filters) self.client.reset_user_credentials() return entities diff --git a/cartoframes/data/observatory/catalog/repository/repo_client.py b/cartoframes/data/observatory/catalog/repository/repo_client.py index 6ef42d99d..1d33b9d3f 100644 --- a/cartoframes/data/observatory/catalog/repository/repo_client.py +++ b/cartoframes/data/observatory/catalog/repository/repo_client.py @@ -73,13 +73,6 @@ def get_variables_groups(self, filters=None): entity = 'datasets/{0}/variables_groups'.format(filters.pop('dataset')) return self._fetch_entity(entity, filters) - def get_entities_filters(self, filters=None): - self.set_external_credentials() - if filters is not None: - filters['filter_catalog'] = False - entities = self._fetch_entity('entities', filters) - return {'id': [result['id'] for result in entities['results']]} - def _get_filter_id(self, filters, use_slug=False): if isinstance(filters, dict): filter_id = filters.get('id') @@ -101,5 +94,7 @@ def _fetch_entity_id(self, entity, filter_id): return self._fetch_entity('{0}/{1}'.format(entity, filter_id)) def _fetch_entity(self, entity, filters=None): + filters = filters or {} + filters['only_products'] = True # Used in dataset/geography endpoints do_dataset = self._user_do_dataset or self._external_do_dataset or self._default_do_dataset return do_dataset.metadata(entity, filters) diff --git a/cartoframes/data/observatory/catalog/subscriptions.py b/cartoframes/data/observatory/catalog/subscriptions.py index ebf098304..82a7e3506 100644 --- a/cartoframes/data/observatory/catalog/subscriptions.py +++ b/cartoframes/data/observatory/catalog/subscriptions.py @@ -10,14 +10,16 @@ class Subscriptions: require a subscription. """ - def __init__(self, datasets, geographies): - self._subscriptions_datasets = datasets - self._subscriptions_geographies = geographies + def __init__(self, credentials): + self._credentials = credentials + self._no_filters = {} + self._datasets = None + self._geographies = None def __repr__(self): return 'Datasets: {0}\nGeographies: {1}'.format( - self._subscriptions_datasets, - self._subscriptions_geographies + self.datasets, + self.geographies ) @property @@ -28,7 +30,10 @@ def datasets(self): CatalogError: if there's a problem when connecting to the catalog. """ - return self._subscriptions_datasets + if self._datasets is None: + from .dataset import Dataset + self._datasets = Dataset.get_all(self._no_filters, self._credentials) + return self._datasets @property def geographies(self): @@ -38,7 +43,10 @@ def geographies(self): CatalogError: if there's a problem when connecting to the catalog. """ - return self._subscriptions_geographies + if self._geographies is None: + from .geography import Geography + self._geographies = Geography.get_all(self._no_filters, self._credentials) + return self._geographies def get_subscription_ids(credentials, stype=None): diff --git a/tests/unit/data/observatory/catalog/repository/test_dataset_repo.py b/tests/unit/data/observatory/catalog/repository/test_dataset_repo.py index cc92d7423..09cd09398 100644 --- a/tests/unit/data/observatory/catalog/repository/test_dataset_repo.py +++ b/tests/unit/data/observatory/catalog/repository/test_dataset_repo.py @@ -18,7 +18,6 @@ class TestDatasetRepo(object): @patch.object(RepoClient, 'get_datasets') - @patch.object(RepoClient, 'get_entities_filters') def test_get_all(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] @@ -34,7 +33,6 @@ def test_get_all(self, mocked_filters, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - @patch.object(RepoClient, 'get_entities_filters') @patch('cartoframes.data.observatory.catalog.repository.entity_repo.get_subscription_ids') def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_filters, mocked_get_datasets): # Given @@ -53,7 +51,6 @@ def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_filters, assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - @patch.object(RepoClient, 'get_entities_filters') def test_get_all_when_empty(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [] @@ -68,7 +65,6 @@ def test_get_all_when_empty(self, mocked_filters, mocked_repo): assert datasets == [] @patch.object(RepoClient, 'get_datasets') - @patch.object(RepoClient, 'get_entities_filters') def test_get_all_only_uses_allowed_filters(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] @@ -98,7 +94,6 @@ def test_get_all_only_uses_allowed_filters(self, mocked_filters, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - @patch.object(RepoClient, 'get_entities_filters') def test_get_by_id(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1] @@ -114,7 +109,6 @@ def test_get_by_id(self, mocked_filters, mocked_repo): assert dataset == test_dataset1 @patch.object(RepoClient, 'get_datasets') - @patch.object(RepoClient, 'get_entities_filters') def test_get_by_id_unknown_fails(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [] @@ -127,7 +121,6 @@ def test_get_by_id_unknown_fails(self, mocked_filters, mocked_repo): repo.get_by_id(requested_id) @patch.object(RepoClient, 'get_datasets') - @patch.object(RepoClient, 'get_entities_filters') def test_get_by_slug(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1] @@ -143,7 +136,6 @@ def test_get_by_slug(self, mocked_filters, mocked_repo): assert dataset == test_dataset1 @patch.object(RepoClient, 'get_datasets') - @patch.object(RepoClient, 'get_entities_filters') def test_get_by_id_list(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] @@ -159,7 +151,6 @@ def test_get_by_id_list(self, mocked_filters, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - @patch.object(RepoClient, 'get_entities_filters') def test_get_by_slug_list(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] @@ -175,7 +166,6 @@ def test_get_by_slug_list(self, mocked_filters, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - @patch.object(RepoClient, 'get_entities_filters') def test_get_by_slug_and_id_list(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] @@ -191,7 +181,6 @@ def test_get_by_slug_and_id_list(self, mocked_filters, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - @patch.object(RepoClient, 'get_entities_filters') def test_missing_fields_are_mapped_as_None(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [{'id': 'dataset1'}] diff --git a/tests/unit/data/observatory/catalog/repository/test_geography_repo.py b/tests/unit/data/observatory/catalog/repository/test_geography_repo.py index 2a4efc612..d6e7b76aa 100644 --- a/tests/unit/data/observatory/catalog/repository/test_geography_repo.py +++ b/tests/unit/data/observatory/catalog/repository/test_geography_repo.py @@ -18,7 +18,6 @@ class TestGeographyRepo(object): @patch.object(RepoClient, 'get_geographies') - @patch.object(RepoClient, 'get_entities_filters') def test_get_all(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] @@ -34,7 +33,6 @@ def test_get_all(self, mocked_filters, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - @patch.object(RepoClient, 'get_entities_filters') @patch('cartoframes.data.observatory.catalog.repository.entity_repo.get_subscription_ids') def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_filters, mocked_get_geographies): # Given @@ -53,7 +51,6 @@ def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_filters, assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - @patch.object(RepoClient, 'get_entities_filters') def test_get_all_when_empty(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [] @@ -68,7 +65,6 @@ def test_get_all_when_empty(self, mocked_filters, mocked_repo): assert geographies == [] @patch.object(RepoClient, 'get_geographies') - @patch.object(RepoClient, 'get_entities_filters') def test_get_all_only_uses_allowed_filters(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] @@ -97,7 +93,6 @@ def test_get_all_only_uses_allowed_filters(self, mocked_filters, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - @patch.object(RepoClient, 'get_entities_filters') def test_get_by_id(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1] @@ -114,7 +109,6 @@ def test_get_by_id(self, mocked_filters, mocked_repo): assert geography == test_geography1 @patch.object(RepoClient, 'get_geographies') - @patch.object(RepoClient, 'get_entities_filters') def test_get_by_id_unknown_fails(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [] @@ -127,7 +121,6 @@ def test_get_by_id_unknown_fails(self, mocked_filters, mocked_repo): repo.get_by_id(requested_id) @patch.object(RepoClient, 'get_geographies') - @patch.object(RepoClient, 'get_entities_filters') def test_get_by_slug(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1] @@ -143,7 +136,6 @@ def test_get_by_slug(self, mocked_filters, mocked_repo): assert geography == test_geography1 @patch.object(RepoClient, 'get_geographies') - @patch.object(RepoClient, 'get_entities_filters') def test_get_by_id_list(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] @@ -159,7 +151,6 @@ def test_get_by_id_list(self, mocked_filters, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - @patch.object(RepoClient, 'get_entities_filters') def test_get_by_slug_list(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] @@ -175,7 +166,6 @@ def test_get_by_slug_list(self, mocked_filters, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - @patch.object(RepoClient, 'get_entities_filters') def test_get_by_slug_and_id_list(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] @@ -191,7 +181,6 @@ def test_get_by_slug_and_id_list(self, mocked_filters, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - @patch.object(RepoClient, 'get_entities_filters') def test_get_all_with_join_filters(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] @@ -207,7 +196,6 @@ def test_get_all_with_join_filters(self, mocked_filters, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - @patch.object(RepoClient, 'get_entities_filters') def test_missing_fields_are_mapped_as_None(self, mocked_filters, mocked_repo): # Given mocked_repo.return_value = [{'id': 'geography1'}] From 80afa9887706ff9c522b35bd4f26704f11f5eea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Fri, 26 Mar 2021 09:40:06 +0100 Subject: [PATCH 21/26] Update tests --- .../catalog/repository/repo_client.py | 2 +- .../catalog/repository/test_dataset_repo.py | 33 ++++++----------- .../catalog/repository/test_geography_repo.py | 36 +++++++------------ .../data/observatory/catalog/test_catalog.py | 8 ++--- 4 files changed, 28 insertions(+), 51 deletions(-) diff --git a/cartoframes/data/observatory/catalog/repository/repo_client.py b/cartoframes/data/observatory/catalog/repository/repo_client.py index 1d33b9d3f..74e50b635 100644 --- a/cartoframes/data/observatory/catalog/repository/repo_client.py +++ b/cartoframes/data/observatory/catalog/repository/repo_client.py @@ -95,6 +95,6 @@ def _fetch_entity_id(self, entity, filter_id): def _fetch_entity(self, entity, filters=None): filters = filters or {} - filters['only_products'] = True # Used in dataset/geography endpoints + filters['only_products'] = True do_dataset = self._user_do_dataset or self._external_do_dataset or self._default_do_dataset return do_dataset.metadata(entity, filters) diff --git a/tests/unit/data/observatory/catalog/repository/test_dataset_repo.py b/tests/unit/data/observatory/catalog/repository/test_dataset_repo.py index 09cd09398..20471a215 100644 --- a/tests/unit/data/observatory/catalog/repository/test_dataset_repo.py +++ b/tests/unit/data/observatory/catalog/repository/test_dataset_repo.py @@ -18,10 +18,9 @@ class TestDatasetRepo(object): @patch.object(RepoClient, 'get_datasets') - def test_get_all(self, mocked_filters, mocked_repo): + def test_get_all(self, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] - mocked_filters.side_effect = lambda f: f repo = DatasetRepository() # When @@ -34,10 +33,9 @@ def test_get_all(self, mocked_filters, mocked_repo): @patch.object(RepoClient, 'get_datasets') @patch('cartoframes.data.observatory.catalog.repository.entity_repo.get_subscription_ids') - def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_filters, mocked_get_datasets): + def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_get_datasets): # Given mocked_get_subscription_ids.return_value = [db_dataset1['id'], db_dataset2['id']] - mocked_filters.side_effect = lambda f: f mocked_get_datasets.return_value = [db_dataset1, db_dataset2] credentials = Credentials('user', '1234') repo = DatasetRepository() @@ -51,10 +49,9 @@ def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_filters, assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - def test_get_all_when_empty(self, mocked_filters, mocked_repo): + def test_get_all_when_empty(self, mocked_repo): # Given mocked_repo.return_value = [] - mocked_filters.side_effect = lambda f: f repo = DatasetRepository() # When @@ -65,10 +62,9 @@ def test_get_all_when_empty(self, mocked_filters, mocked_repo): assert datasets == [] @patch.object(RepoClient, 'get_datasets') - def test_get_all_only_uses_allowed_filters(self, mocked_filters, mocked_repo): + def test_get_all_only_uses_allowed_filters(self, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] - mocked_filters.side_effect = lambda f: f repo = DatasetRepository() filters = { COUNTRY_FILTER: 'usa', @@ -94,10 +90,9 @@ def test_get_all_only_uses_allowed_filters(self, mocked_filters, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - def test_get_by_id(self, mocked_filters, mocked_repo): + def test_get_by_id(self, mocked_repo): # Given mocked_repo.return_value = [db_dataset1] - mocked_filters.side_effect = lambda f: f requested_id = db_dataset1['id'] repo = DatasetRepository() @@ -109,10 +104,9 @@ def test_get_by_id(self, mocked_filters, mocked_repo): assert dataset == test_dataset1 @patch.object(RepoClient, 'get_datasets') - def test_get_by_id_unknown_fails(self, mocked_filters, mocked_repo): + def test_get_by_id_unknown_fails(self, mocked_repo): # Given mocked_repo.return_value = [] - mocked_filters.side_effect = lambda f: f requested_id = 'unknown_id' repo = DatasetRepository() @@ -121,10 +115,9 @@ def test_get_by_id_unknown_fails(self, mocked_filters, mocked_repo): repo.get_by_id(requested_id) @patch.object(RepoClient, 'get_datasets') - def test_get_by_slug(self, mocked_filters, mocked_repo): + def test_get_by_slug(self, mocked_repo): # Given mocked_repo.return_value = [db_dataset1] - mocked_filters.side_effect = lambda f: f requested_slug = db_dataset1['slug'] repo = DatasetRepository() @@ -136,10 +129,9 @@ def test_get_by_slug(self, mocked_filters, mocked_repo): assert dataset == test_dataset1 @patch.object(RepoClient, 'get_datasets') - def test_get_by_id_list(self, mocked_filters, mocked_repo): + def test_get_by_id_list(self, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] - mocked_filters.side_effect = lambda f: f repo = DatasetRepository() # When @@ -151,10 +143,9 @@ def test_get_by_id_list(self, mocked_filters, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - def test_get_by_slug_list(self, mocked_filters, mocked_repo): + def test_get_by_slug_list(self, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] - mocked_filters.side_effect = lambda f: f repo = DatasetRepository() # When @@ -166,10 +157,9 @@ def test_get_by_slug_list(self, mocked_filters, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - def test_get_by_slug_and_id_list(self, mocked_filters, mocked_repo): + def test_get_by_slug_and_id_list(self, mocked_repo): # Given mocked_repo.return_value = [db_dataset1, db_dataset2] - mocked_filters.side_effect = lambda f: f repo = DatasetRepository() # When @@ -181,10 +171,9 @@ def test_get_by_slug_and_id_list(self, mocked_filters, mocked_repo): assert datasets == test_datasets @patch.object(RepoClient, 'get_datasets') - def test_missing_fields_are_mapped_as_None(self, mocked_filters, mocked_repo): + def test_missing_fields_are_mapped_as_None(self, mocked_repo): # Given mocked_repo.return_value = [{'id': 'dataset1'}] - mocked_filters.side_effect = lambda f: f repo = DatasetRepository() expected_datasets = CatalogList([Dataset({ diff --git a/tests/unit/data/observatory/catalog/repository/test_geography_repo.py b/tests/unit/data/observatory/catalog/repository/test_geography_repo.py index d6e7b76aa..5a1ed0011 100644 --- a/tests/unit/data/observatory/catalog/repository/test_geography_repo.py +++ b/tests/unit/data/observatory/catalog/repository/test_geography_repo.py @@ -18,10 +18,9 @@ class TestGeographyRepo(object): @patch.object(RepoClient, 'get_geographies') - def test_get_all(self, mocked_filters, mocked_repo): + def test_get_all(self, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] - mocked_filters.side_effect = lambda f: f repo = GeographyRepository() # When @@ -34,10 +33,9 @@ def test_get_all(self, mocked_filters, mocked_repo): @patch.object(RepoClient, 'get_geographies') @patch('cartoframes.data.observatory.catalog.repository.entity_repo.get_subscription_ids') - def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_filters, mocked_get_geographies): + def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_get_geographies): # Given mocked_get_subscription_ids.return_value = [db_geography1['id'], db_geography2['id']] - mocked_filters.side_effect = lambda f: f mocked_get_geographies.return_value = [db_geography1, db_geography2] credentials = Credentials('user', '1234') repo = GeographyRepository() @@ -51,10 +49,9 @@ def test_get_all_credentials(self, mocked_get_subscription_ids, mocked_filters, assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - def test_get_all_when_empty(self, mocked_filters, mocked_repo): + def test_get_all_when_empty(self, mocked_repo): # Given mocked_repo.return_value = [] - mocked_filters.side_effect = lambda f: f repo = GeographyRepository() # When @@ -65,10 +62,9 @@ def test_get_all_when_empty(self, mocked_filters, mocked_repo): assert geographies == [] @patch.object(RepoClient, 'get_geographies') - def test_get_all_only_uses_allowed_filters(self, mocked_filters, mocked_repo): + def test_get_all_only_uses_allowed_filters(self, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] - mocked_filters.side_effect = lambda f: f repo = GeographyRepository() filters = { COUNTRY_FILTER: 'usa', @@ -93,10 +89,9 @@ def test_get_all_only_uses_allowed_filters(self, mocked_filters, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - def test_get_by_id(self, mocked_filters, mocked_repo): + def test_get_by_id(self, mocked_repo): # Given mocked_repo.return_value = [db_geography1] - mocked_filters.side_effect = lambda f: f requested_id = db_geography1['id'] repo = GeographyRepository() @@ -109,10 +104,9 @@ def test_get_by_id(self, mocked_filters, mocked_repo): assert geography == test_geography1 @patch.object(RepoClient, 'get_geographies') - def test_get_by_id_unknown_fails(self, mocked_filters, mocked_repo): + def test_get_by_id_unknown_fails(self, mocked_repo): # Given mocked_repo.return_value = [] - mocked_filters.side_effect = lambda f: f requested_id = 'unknown_id' repo = GeographyRepository() @@ -121,10 +115,9 @@ def test_get_by_id_unknown_fails(self, mocked_filters, mocked_repo): repo.get_by_id(requested_id) @patch.object(RepoClient, 'get_geographies') - def test_get_by_slug(self, mocked_filters, mocked_repo): + def test_get_by_slug(self, mocked_repo): # Given mocked_repo.return_value = [db_geography1] - mocked_filters.side_effect = lambda f: f requested_slug = db_geography1['slug'] repo = GeographyRepository() @@ -136,10 +129,9 @@ def test_get_by_slug(self, mocked_filters, mocked_repo): assert geography == test_geography1 @patch.object(RepoClient, 'get_geographies') - def test_get_by_id_list(self, mocked_filters, mocked_repo): + def test_get_by_id_list(self, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] - mocked_filters.side_effect = lambda f: f repo = GeographyRepository() # When @@ -151,10 +143,9 @@ def test_get_by_id_list(self, mocked_filters, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - def test_get_by_slug_list(self, mocked_filters, mocked_repo): + def test_get_by_slug_list(self, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] - mocked_filters.side_effect = lambda f: f repo = GeographyRepository() # When @@ -166,10 +157,9 @@ def test_get_by_slug_list(self, mocked_filters, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - def test_get_by_slug_and_id_list(self, mocked_filters, mocked_repo): + def test_get_by_slug_and_id_list(self, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] - mocked_filters.side_effect = lambda f: f repo = GeographyRepository() # When @@ -181,10 +171,9 @@ def test_get_by_slug_and_id_list(self, mocked_filters, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - def test_get_all_with_join_filters(self, mocked_filters, mocked_repo): + def test_get_all_with_join_filters(self, mocked_repo): # Given mocked_repo.return_value = [db_geography1, db_geography2] - mocked_filters.side_effect = lambda f: f repo = GeographyRepository() # When @@ -196,10 +185,9 @@ def test_get_all_with_join_filters(self, mocked_filters, mocked_repo): assert geographies == test_geographies @patch.object(RepoClient, 'get_geographies') - def test_missing_fields_are_mapped_as_None(self, mocked_filters, mocked_repo): + def test_missing_fields_are_mapped_as_None(self, mocked_repo): # Given mocked_repo.return_value = [{'id': 'geography1'}] - mocked_filters.side_effect = lambda f: f repo = GeographyRepository() expected_geographies = CatalogList([Geography({ diff --git a/tests/unit/data/observatory/catalog/test_catalog.py b/tests/unit/data/observatory/catalog/test_catalog.py index 8d0b78037..ffdd590ea 100644 --- a/tests/unit/data/observatory/catalog/test_catalog.py +++ b/tests/unit/data/observatory/catalog/test_catalog.py @@ -235,11 +235,11 @@ def test_subscriptions(self, mocked_geographies, mocked_datasets): subscriptions = catalog.subscriptions(credentials) # Then - mocked_datasets.assert_called_once_with({}, credentials) - mocked_geographies.assert_called_once_with({}, credentials) assert isinstance(subscriptions, Subscriptions) assert subscriptions.datasets == expected_datasets assert subscriptions.geographies == expected_geographies + mocked_datasets.assert_called_once_with({}, credentials) + mocked_geographies.assert_called_once_with({}, credentials) @patch.object(Dataset, 'get_all') @patch.object(Geography, 'get_all') @@ -258,11 +258,11 @@ def test_subscriptions_default_credentials(self, mocked_credentials, mocked_geog subscriptions = catalog.subscriptions() # Then - mocked_datasets.assert_called_once_with({}, expected_credentials) - mocked_geographies.assert_called_once_with({}, expected_credentials) assert isinstance(subscriptions, Subscriptions) assert subscriptions.datasets == expected_datasets assert subscriptions.geographies == expected_geographies + mocked_datasets.assert_called_once_with({}, expected_credentials) + mocked_geographies.assert_called_once_with({}, expected_credentials) @patch.object(Dataset, 'get_all') @patch.object(Geography, 'get_all') From 512a4b0a043df78bf389078a6af899f8510a9cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Fri, 26 Mar 2021 09:59:13 +0100 Subject: [PATCH 22/26] Update guides --- CHANGELOG.md | 2 +- docs/guides/01-Installation.ipynb | 2 +- docs/guides/02-Authentication.ipynb | 2 +- docs/guides/03-Quickstart.ipynb | 370 ++++++++++++------------ docs/guides/04-Data-Management.ipynb | 14 +- docs/guides/05-Data-Visualization.ipynb | 58 ++-- docs/guides/06-Data-Services.ipynb | 78 ++--- tests/README.md | 2 + tests/notebooks/requirements.txt | 1 + tests/notebooks/test_notebooks.py | 17 +- 10 files changed, 279 insertions(+), 267 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0dae4fd2..311998e84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.2.0] - 2021-03-26 ### Changed -- Filter only product entities in subscriptions (#1723) +- Filter only product entities in subscriptions (#1723, #1728) - Dataset describe not in scientific notation (#1722) - Review and improve SQLClient utilities (#1725) diff --git a/docs/guides/01-Installation.ipynb b/docs/guides/01-Installation.ipynb index 162315339..59788e3f0 100644 --- a/docs/guides/01-Installation.ipynb +++ b/docs/guides/01-Installation.ipynb @@ -123,7 +123,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.8.5" } }, "nbformat": 4, diff --git a/docs/guides/02-Authentication.ipynb b/docs/guides/02-Authentication.ipynb index 73adaf9c2..e33d68582 100644 --- a/docs/guides/02-Authentication.ipynb +++ b/docs/guides/02-Authentication.ipynb @@ -115,7 +115,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.8.5" } }, "nbformat": 4, diff --git a/docs/guides/03-Quickstart.ipynb b/docs/guides/03-Quickstart.ipynb index 85da8e650..c731135ca 100644 --- a/docs/guides/03-Quickstart.ipynb +++ b/docs/guides/03-Quickstart.ipynb @@ -140,7 +140,7 @@ "4 1148427.411 " ] }, - "execution_count": 2, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -295,7 +295,7 @@ "4 134c23973313802448365db6235783f9 " ] }, - "execution_count": 4, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -1539,7 +1539,7 @@ " const has_legends = 'False' === 'true';\n", " const is_static = 'None' === 'true';\n", " const layer_selector = 'False' === 'true';\n", - " const layers = [{"credentials": null, "data": "H4sIAGoVyl8C/7XSTYvDIBAG4P/iOQ06fozTa6HnvZceSusuQhuDdQ8l5L/X2CyYu3vM8JqHd5iJpdfo2J4d3SX9RncI97u7Jh8G1rHvz+zJ9qeJ+VtO8TzdPsiDMYbRxeSX4DR37MeFh0vxlb/+wl/BDylHryHEmx8uqfx0h7Injcp0ivcGBYfzPHcrJdpTRgAslEYkU1HQnrKEtrQSpFRFycaU6jmgLpKEzf5Ue4lzKqU0SRAVpdvvj8CI0spaRRVlmlMWufgsUEuhKwrbL1BKIderAKwo+w8HqHS5dUObUtReUhZhPUBYqPP8BlYpQ3lVBAAA", "encode_data": true, "has_legend_list": true, "interactivity": [], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAGoVyl8C/7XSTYvDIBAG4P/iOQ06fozTa6HnvZceSusuQhuDdQ8l5L/X2CyYu3vM8JqHd5iJpdfo2J4d3SX9RncI97u7Jh8G1rHvz+zJ9qeJ+VtO8TzdPsiDMYbRxeSX4DR37MeFh0vxlb/+wl/BDylHryHEmx8uqfx0h7Injcp0ivcGBYfzPHcrJdpTRgAslEYkU1HQnrKEtrQSpFRFycaU6jmgLpKEzf5Ue4lzKqU0SRAVpdvvj8CI0spaRRVlmlMWufgsUEuhKwrbL1BKIderAKwo+w8HqHS5dUObUtReUhZhPUBYqPP8BlYpQ3lVBAAA", "title": null, "type": "GeoJSON", "viz": "color: hex(\\"#EE4D5A\\")\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(zoom(),0,18),[2,10])\\n", "widgets": []}];\n", + " const layers = [{"credentials": null, "data": "H4sIAMCfXWAC/7XSTYvDIBAG4P/iOQ06fozTa6HnvZceSusuQhuDdQ8l5L/X2CyYu3vM8JqHd5iJpdfo2J4d3SX9RncI97u7Jh8G1rHvz+zJ9qeJ+VtO8TzdPsiDMYbRxeSX4DR37MeFh0vxlb/+wl/BDylHryHEmx8uqfx0h7Injcp0ivcGBYfzPHcrJdpTRgAslEYkU1HQnrKEtrQSpFRFycaU6jmgLpKEzf5Ue4lzKqU0SRAVpdvvj8CI0spaRRVlmlMWufgsUEuhKwrbL1BKIderAKwo+w8HqHS5dUObUtReUhZhPUBYqPP8BlYpQ3lVBAAA", "encode_data": true, "has_legend_list": true, "interactivity": [], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAMCfXWAC/7XSTYvDIBAG4P/iOQ06fozTa6HnvZceSusuQhuDdQ8l5L/X2CyYu3vM8JqHd5iJpdfo2J4d3SX9RncI97u7Jh8G1rHvz+zJ9qeJ+VtO8TzdPsiDMYbRxeSX4DR37MeFh0vxlb/+wl/BDylHryHEmx8uqfx0h7Injcp0ivcGBYfzPHcrJdpTRgAslEYkU1HQnrKEtrQSpFRFycaU6jmgLpKEzf5Ue4lzKqU0SRAVpdvvj8CI0spaRRVlmlMWufgsUEuhKwrbL1BKIderAKwo+w8HqHS5dUObUtReUhZhPUBYqPP8BlYpQ3lVBAAA", "title": null, "type": "GeoJSON", "viz": "color: hex(\\"#EE4D5A\\")\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(zoom(),0,18),[2,10])\\n", "widgets": []}];\n", " const mapboxtoken = '';\n", " const show_info = 'None' === 'true';\n", "\n", @@ -1563,10 +1563,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 5, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -2838,7 +2838,7 @@ " const has_legends = 'true' === 'true';\n", " const is_static = 'None' === 'true';\n", " const layer_selector = 'False' === 'true';\n", - " const layers = [{"credentials": null, "data": "H4sIAGoVyl8C/52TvW7DMAyE30WzK0gUxZ+sBTp3LzIEiVoYSO3AdQoEgd+9suPBGVmNBOnvfDze3Xi7FLdzb+UwXofy2p/P5Ti2feca9/mo/bjdx921p9oVavV5oBYuQ38pw9jOjXc3lN/SXWtHTBADBs8MU+O+Sv9dxuE2t6xfeO/bbqzzx74fTm13GBfSCyevmZGaOkscA+ynqVn50cIHkiDBYxQznyLAzM/MShs+mPgoMSVPqma+KMvy/1ERN/xk4UfJHKB6SDY++gCcF3yCJ/vRhEdB4Gp/0OWJWUUIuriQtUZpIyPbZGAg8kTZvAUFiosNIqgbPln4oV6BpGqphuVFqwzhEB/byCnmjQw2yFCoWWCfEtjDkFJMaxiBN3wx8Jkya/JIaxj+cRKYl5MkfTJBLSJQIZJPUcxLUBSG9SRg5u+nP/xeZSY7BQAA", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "vabf72c", "title": "Annual Revenue ($)"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "width", "title": "Annual Revenue ($)", "type": "size-continuous", "variable": "size_value"}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAGoVyl8C/52TvW7DMAyE30WzK0gUxZ+sBTp3LzIEiVoYSO3AdQoEgd+9suPBGVmNBOnvfDze3Xi7FLdzb+UwXofy2p/P5Ti2feca9/mo/bjdx921p9oVavV5oBYuQ38pw9jOjXc3lN/SXWtHTBADBs8MU+O+Sv9dxuE2t6xfeO/bbqzzx74fTm13GBfSCyevmZGaOkscA+ynqVn50cIHkiDBYxQznyLAzM/MShs+mPgoMSVPqma+KMvy/1ERN/xk4UfJHKB6SDY++gCcF3yCJ/vRhEdB4Gp/0OWJWUUIuriQtUZpIyPbZGAg8kTZvAUFiosNIqgbPln4oV6BpGqphuVFqwzhEB/byCnmjQw2yFCoWWCfEtjDkFJMaxiBN3wx8Jkya/JIaxj+cRKYl5MkfTJBLSJQIZJPUcxLUBSG9SRg5u+nP/xeZSY7BQAA", "title": "Annual Revenue ($)", "type": "GeoJSON", "viz": "@vabf72c: prop(\\u0027revenue\\u0027)\\n@size_value: ramp(linear(prop(\\u0027revenue\\u0027), globalMIN(prop(\\u0027revenue\\u0027)), globalMAX(prop(\\u0027revenue\\u0027))), [10, 40])\\ncolor: opacity(#FFB927, 0.8)\\nfilter: 1\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(sqrt(prop(\\u0027revenue\\u0027)), sqrt(globalMIN(prop(\\u0027revenue\\u0027))), sqrt(globalMAX(prop(\\u0027revenue\\u0027)))), [10, 40])\\n", "widgets": []}];\n", + " const layers = [{"credentials": null, "data": "H4sIAMCfXWAC/5XTTWvDMAwG4P/ic2asD0t2r4Wddx89lNYbgS4pWTooJf99TppDetRVyHnQK+Xhxvu1uJ17L8fxNpR9f7mU09j2nWvc17P263afD9eea1eo1dcHtXAd+msZxnZufLih/JXuVjuAEAIHr4pT475L/1PG4T63rF/46NturO9PfT+c2+44LtKbks9RWZr6VhQCHqapWX2w+CgppOAZktkXQJz9qJpl46PJ5wREXnI2+ylrWuaHzLzxyeJDihqwZig2n31AjQtP+BI/m3hOjFrjBzMfQl7Gj7ne0MaPNp+DiBeJ5vgzCizzp8R544vFD/X8E9UszetPGuCZfySIG18Nfsa6ffVEaF8/EdB6fqgbPxl8laiZPAvYr5/j8vdJfpk+W3TOCOIJkp3npLheP87+YfoHPW7k4CYFAAA=", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "vabf72c", "title": "Annual Revenue ($)"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "width", "title": "Annual Revenue ($)", "type": "size-continuous", "variable": "size_value"}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAMCfXWAC/5XTTWvDMAwG4P/ic2asD0t2r4Wddx89lNYbgS4pWTooJf99TppDetRVyHnQK+Xhxvu1uJ17L8fxNpR9f7mU09j2nWvc17P263afD9eea1eo1dcHtXAd+msZxnZufLih/JXuVjuAEAIHr4pT475L/1PG4T63rF/46NturO9PfT+c2+44LtKbks9RWZr6VhQCHqapWX2w+CgppOAZktkXQJz9qJpl46PJ5wREXnI2+ylrWuaHzLzxyeJDihqwZig2n31AjQtP+BI/m3hOjFrjBzMfQl7Gj7ne0MaPNp+DiBeJ5vgzCizzp8R544vFD/X8E9UszetPGuCZfySIG18Nfsa6ffVEaF8/EdB6fqgbPxl8laiZPAvYr5/j8vdJfpk+W3TOCOIJkp3npLheP87+YfoHPW7k4CYFAAA=", "title": "Annual Revenue ($)", "type": "GeoJSON", "viz": "@vabf72c: prop(\\u0027revenue\\u0027)\\n@size_value: ramp(linear(prop(\\u0027revenue\\u0027), globalMIN(prop(\\u0027revenue\\u0027)), globalMAX(prop(\\u0027revenue\\u0027))), [10, 40])\\ncolor: opacity(#FFB927, 0.8)\\nfilter: 1\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(sqrt(prop(\\u0027revenue\\u0027)), sqrt(globalMIN(prop(\\u0027revenue\\u0027))), sqrt(globalMAX(prop(\\u0027revenue\\u0027)))), [10, 40])\\n", "widgets": []}];\n", " const mapboxtoken = '';\n", " const show_info = 'None' === 'true';\n", "\n", @@ -2862,10 +2862,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 6, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -2939,31 +2939,31 @@ " 0\n", " 0\n", " 900\n", - " MULTIPOLYGON (((-73.96743 40.67345, -73.96683 ...\n", + " MULTIPOLYGON (((-73.96811 40.67413, -73.96751 ...\n", " \n", " \n", " 1\n", " 1\n", " 900\n", - " MULTIPOLYGON (((-73.97035 40.57749, -73.97009 ...\n", + " MULTIPOLYGON (((-73.97155 40.57732, -73.97112 ...\n", " \n", " \n", " 2\n", " 2\n", " 900\n", - " MULTIPOLYGON (((-73.99781 40.62418, -73.99755 ...\n", + " MULTIPOLYGON (((-73.99833 40.62538, -73.99361 ...\n", " \n", " \n", " 3\n", " 3\n", " 900\n", - " MULTIPOLYGON (((-74.03678 40.63431, -74.03618 ...\n", + " MULTIPOLYGON (((-74.03764 40.63448, -74.03738 ...\n", " \n", " \n", " 4\n", " 4\n", " 900\n", - " MULTIPOLYGON (((-74.00451 40.59723, -74.00391 ...\n", + " MULTIPOLYGON (((-74.00519 40.59792, -74.00391 ...\n", " \n", " \n", "\n", @@ -2971,14 +2971,14 @@ ], "text/plain": [ " source_id data_range the_geom\n", - "0 0 900 MULTIPOLYGON (((-73.96743 40.67345, -73.96683 ...\n", - "1 1 900 MULTIPOLYGON (((-73.97035 40.57749, -73.97009 ...\n", - "2 2 900 MULTIPOLYGON (((-73.99781 40.62418, -73.99755 ...\n", - "3 3 900 MULTIPOLYGON (((-74.03678 40.63431, -74.03618 ...\n", - "4 4 900 MULTIPOLYGON (((-74.00451 40.59723, -74.00391 ..." + "0 0 900 MULTIPOLYGON (((-73.96811 40.67413, -73.96751 ...\n", + "1 1 900 MULTIPOLYGON (((-73.97155 40.57732, -73.97112 ...\n", + "2 2 900 MULTIPOLYGON (((-73.99833 40.62538, -73.99361 ...\n", + "3 3 900 MULTIPOLYGON (((-74.03764 40.63448, -74.03738 ...\n", + "4 4 900 MULTIPOLYGON (((-74.00519 40.59792, -74.00391 ..." ] }, - "execution_count": 7, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -4239,12 +4239,12 @@ " .addEventListener('ready', () => {\n", " const basecolor = '';\n", " const basemap = 'Positron';\n", - " const bounds = [[-74.0416718, 40.5738831], [-73.8652039, 40.6988525]];\n", + " const bounds = [[-74.043045, 40.5738831], [-73.8638306, 40.6988525]];\n", " const camera = null;\n", " const has_legends = 'true' === 'true';\n", " const is_static = 'None' === 'true';\n", " const layer_selector = 'False' === 'true';\n", - " const layers = [{"credentials": null, "data": "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", "encode_data": true, "has_legend_list": true, "interactivity": [], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "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", "title": null, "type": "GeoJSON", "viz": "color: hex(\\"#826DBA\\")\\nstrokeColor: opacity(#2c2c2c,ramp(linear(zoom(),2,18),[0.2,0.6]))\\nstrokeWidth: ramp(linear(zoom(),2,18),[0.5,1])\\n", "widgets": []}, {"credentials": null, "data": "H4sIAHMVyl8C/52TvW7DMAyE30WzK0gUxZ+sBTp3LzIEiVoYSO3AdQoEgd+9suPBGVmNBOnvfDze3Xi7FLdzb+UwXofy2p/P5Ti2feca9/mo/bjdx921p9oVavV5oBYuQ38pw9jOjXc3lN/SXWtHTBADBs8MU+O+Sv9dxuE2t6xfeO/bbqzzx74fTm13GBfSCyevmZGaOkscA+ynqVn50cIHkiDBYxQznyLAzM/MShs+mPgoMSVPqma+KMvy/1ERN/xk4UfJHKB6SDY++gCcF3yCJ/vRhEdB4Gp/0OWJWUUIuriQtUZpIyPbZGAg8kTZvAUFiosNIqgbPln4oV6BpGqphuVFqwzhEB/byCnmjQw2yFCoWWCfEtjDkFJMaxiBN3wx8Jkya/JIaxj+cRKYl5MkfTJBLSJQIZJPUcxLUBSG9SRg5u+nP/xeZSY7BQAA", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "vabf72c", "title": "Annual Revenue ($)"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "width", "title": "Annual Revenue ($)", "type": "size-continuous", "variable": "size_value"}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAHMVyl8C/52TvW7DMAyE30WzK0gUxZ+sBTp3LzIEiVoYSO3AdQoEgd+9suPBGVmNBOnvfDze3Xi7FLdzb+UwXofy2p/P5Ti2feca9/mo/bjdx921p9oVavV5oBYuQ38pw9jOjXc3lN/SXWtHTBADBs8MU+O+Sv9dxuE2t6xfeO/bbqzzx74fTm13GBfSCyevmZGaOkscA+ynqVn50cIHkiDBYxQznyLAzM/MShs+mPgoMSVPqma+KMvy/1ERN/xk4UfJHKB6SDY++gCcF3yCJ/vRhEdB4Gp/0OWJWUUIuriQtUZpIyPbZGAg8kTZvAUFiosNIqgbPln4oV6BpGqphuVFqwzhEB/byCnmjQw2yFCoWWCfEtjDkFJMaxiBN3wx8Jkya/JIaxj+cRKYl5MkfTJBLSJQIZJPUcxLUBSG9SRg5u+nP/xeZSY7BQAA", "title": "Annual Revenue ($)", "type": "GeoJSON", "viz": "@vabf72c: prop(\\u0027revenue\\u0027)\\n@size_value: ramp(linear(prop(\\u0027revenue\\u0027), globalMIN(prop(\\u0027revenue\\u0027)), globalMAX(prop(\\u0027revenue\\u0027))), [10, 40])\\ncolor: opacity(#FFB927, 0.8)\\nfilter: 1\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(sqrt(prop(\\u0027revenue\\u0027)), sqrt(globalMIN(prop(\\u0027revenue\\u0027))), sqrt(globalMAX(prop(\\u0027revenue\\u0027)))), [10, 40])\\n", "widgets": []}];\n", + " const layers = [{"credentials": null, "data": "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", "encode_data": true, "has_legend_list": true, "interactivity": [], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "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", "title": null, "type": "GeoJSON", "viz": "color: hex(\\"#826DBA\\")\\nstrokeColor: opacity(#2c2c2c,ramp(linear(zoom(),2,18),[0.2,0.6]))\\nstrokeWidth: ramp(linear(zoom(),2,18),[0.5,1])\\n", "widgets": []}, {"credentials": null, "data": "H4sIAMmfXWAC/5XTTWvDMAwG4P/ic2asD0t2r4Wddx89lNYbgS4pWTooJf99TppDetRVyHnQK+Xhxvu1uJ17L8fxNpR9f7mU09j2nWvc17P263afD9eea1eo1dcHtXAd+msZxnZufLih/JXuVjuAEAIHr4pT475L/1PG4T63rF/46NturO9PfT+c2+44LtKbks9RWZr6VhQCHqapWX2w+CgppOAZktkXQJz9qJpl46PJ5wREXnI2+ylrWuaHzLzxyeJDihqwZig2n31AjQtP+BI/m3hOjFrjBzMfQl7Gj7ne0MaPNp+DiBeJ5vgzCizzp8R544vFD/X8E9UszetPGuCZfySIG18Nfsa6ffVEaF8/EdB6fqgbPxl8laiZPAvYr5/j8vdJfpk+W3TOCOIJkp3npLheP87+YfoHPW7k4CYFAAA=", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "vabf72c", "title": "Annual Revenue ($)"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "width", "title": "Annual Revenue ($)", "type": "size-continuous", "variable": "size_value"}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAMmfXWAC/5XTTWvDMAwG4P/ic2asD0t2r4Wddx89lNYbgS4pWTooJf99TppDetRVyHnQK+Xhxvu1uJ17L8fxNpR9f7mU09j2nWvc17P263afD9eea1eo1dcHtXAd+msZxnZufLih/JXuVjuAEAIHr4pT475L/1PG4T63rF/46NturO9PfT+c2+44LtKbks9RWZr6VhQCHqapWX2w+CgppOAZktkXQJz9qJpl46PJ5wREXnI2+ylrWuaHzLzxyeJDihqwZig2n31AjQtP+BI/m3hOjFrjBzMfQl7Gj7ne0MaPNp+DiBeJ5vgzCizzp8R544vFD/X8E9UszetPGuCZfySIG18Nfsa6ffVEaF8/EdB6fqgbPxl8laiZPAvYr5/j8vdJfpk+W3TOCOIJkp3npLheP87+YfoHPW7k4CYFAAA=", "title": "Annual Revenue ($)", "type": "GeoJSON", "viz": "@vabf72c: prop(\\u0027revenue\\u0027)\\n@size_value: ramp(linear(prop(\\u0027revenue\\u0027), globalMIN(prop(\\u0027revenue\\u0027)), globalMAX(prop(\\u0027revenue\\u0027))), [10, 40])\\ncolor: opacity(#FFB927, 0.8)\\nfilter: 1\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(sqrt(prop(\\u0027revenue\\u0027)), sqrt(globalMIN(prop(\\u0027revenue\\u0027))), sqrt(globalMAX(prop(\\u0027revenue\\u0027)))), [10, 40])\\n", "widgets": []}];\n", " const mapboxtoken = '';\n", " const show_info = 'None' === 'true';\n", "\n", @@ -4268,10 +4268,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 8, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -4377,7 +4377,7 @@ " Global grid at aprox. 1-kilometer resolution (...\n", " yearly\n", " [2020-01-01, 2021-01-01)\n", - " yearly\n", + " None\n", " True\n", " eng\n", " 2020\n", @@ -4399,7 +4399,7 @@ " Global grid at aprox. 1-kilometer resolution (...\n", " yearly\n", " [2019-01-01, 2020-01-01)\n", - " yearly\n", + " None\n", " True\n", " eng\n", " 2019\n", @@ -4421,7 +4421,7 @@ " Global grid at aprox. 1-kilometer resolution (...\n", " yearly\n", " [2018-01-01, 2019-01-01)\n", - " yearly\n", + " None\n", " True\n", " eng\n", " 2018\n", @@ -4443,7 +4443,7 @@ " Global grid at aprox. 1-kilometer resolution (...\n", " yearly\n", " [2017-01-01, 2018-01-01)\n", - " yearly\n", + " None\n", " True\n", " eng\n", " 2017\n", @@ -4465,7 +4465,7 @@ " Global grid at aprox. 1-kilometer resolution (...\n", " yearly\n", " [2016-01-01, 2017-01-01)\n", - " yearly\n", + " None\n", " True\n", " eng\n", " 2016\n", @@ -4497,113 +4497,113 @@ " ...\n", " \n", " \n", - " 530\n", - " bls_labor_35c98360\n", - " Labor - United States of America (County, 1992Q1)\n", - " Extract from the Quarterly Census of Emploment...\n", + " 527\n", + " acs_sociodemogr_bd7ed0dc\n", + " Sociodemographics - United States of America (...\n", + " The American Community Survey (ACS) is an ongo...\n", " demographics\n", " usa\n", - " labor\n", - " usa_bls\n", - " County - United States of America (2018)\n", + " sociodemographics\n", + " usa_acs\n", + " Public Use Microdata Area - United States of A...\n", " Shoreline clipped TIGER/Line boundaries. More ...\n", - " quarterly\n", - " [1992-01-01, 1992-04-01)\n", - " quarterly\n", + " yearly\n", + " [2016-01-01, 2017-01-01)\n", + " None\n", " True\n", " eng\n", - " 1992q1\n", + " 2016\n", " Demographics\n", - " Bureau of Labor Statistics\n", - " carto-do-public-data.carto.geography_usa_count...\n", - " carto-do-public-data.usa_bls.demographics_labo...\n", + " American Community Survey\n", + " carto-do-public-data.carto.geography_usa_puma_...\n", + " carto-do-public-data.usa_acs.demographics_soci...\n", " \n", " \n", - " 531\n", - " bls_labor_2c89d72e\n", - " Labor - United States of America (County, 2003Q3)\n", - " Extract from the Quarterly Census of Emploment...\n", + " 530\n", + " acs_sociodemogr_8e66b3d3\n", + " Sociodemographics - United States of America (...\n", + " The American Community Survey (ACS) is an ongo...\n", " demographics\n", " usa\n", - " labor\n", - " usa_bls\n", - " County - United States of America (2018)\n", + " sociodemographics\n", + " usa_acs\n", + " Census Place - United States of America (2019)\n", " Shoreline clipped TIGER/Line boundaries. More ...\n", - " quarterly\n", - " [2003-07-01, 2003-10-01)\n", - " quarterly\n", + " yearly\n", + " [2011-01-01, 2012-01-01)\n", + " None\n", " True\n", " eng\n", - " 2003q3\n", + " 2011\n", " Demographics\n", - " Bureau of Labor Statistics\n", - " carto-do-public-data.carto.geography_usa_count...\n", - " carto-do-public-data.usa_bls.demographics_labo...\n", + " American Community Survey\n", + " carto-do-public-data.carto.geography_usa_place...\n", + " carto-do-public-data.usa_acs.demographics_soci...\n", " \n", " \n", " 532\n", - " bls_labor_2d4bbd19\n", - " Labor - United States of America (County, 2002Q3)\n", - " Extract from the Quarterly Census of Emploment...\n", + " acs_sociodemogr_6347604c\n", + " Sociodemographics - United States of America (...\n", + " The American Community Survey (ACS) is an ongo...\n", " demographics\n", " usa\n", - " labor\n", - " usa_bls\n", - " County - United States of America (2018)\n", + " sociodemographics\n", + " usa_acs\n", + " Public Use Microdata Area - United States of A...\n", " Shoreline clipped TIGER/Line boundaries. More ...\n", - " quarterly\n", - " [2002-07-01, 2002-10-01)\n", - " quarterly\n", + " 3yrs\n", + " [2009-01-01, 2012-01-01)\n", + " None\n", " True\n", " eng\n", - " 2002q3\n", + " 20092011\n", " Demographics\n", - " Bureau of Labor Statistics\n", - " carto-do-public-data.carto.geography_usa_count...\n", - " carto-do-public-data.usa_bls.demographics_labo...\n", + " American Community Survey\n", + " carto-do-public-data.carto.geography_usa_puma_...\n", + " carto-do-public-data.usa_acs.demographics_soci...\n", " \n", " \n", " 533\n", - " bls_labor_933c1897\n", - " Labor - United States of America (County, 2017Q3)\n", - " Extract from the Quarterly Census of Emploment...\n", + " acs_sociodemogr_231a457f\n", + " Sociodemographics - United States of America (...\n", + " The American Community Survey (ACS) is an ongo...\n", " demographics\n", " usa\n", - " labor\n", - " usa_bls\n", - " County - United States of America (2018)\n", + " sociodemographics\n", + " usa_acs\n", + " Public Use Microdata Area - United States of A...\n", " Shoreline clipped TIGER/Line boundaries. More ...\n", - " quarterly\n", - " [2017-07-01, 2017-10-01)\n", - " quarterly\n", + " yearly\n", + " [2011-01-01, 2012-01-01)\n", + " None\n", " True\n", " eng\n", - " 2017q3\n", + " 2011\n", " Demographics\n", - " Bureau of Labor Statistics\n", - " carto-do-public-data.carto.geography_usa_count...\n", - " carto-do-public-data.usa_bls.demographics_labo...\n", + " American Community Survey\n", + " carto-do-public-data.carto.geography_usa_puma_...\n", + " carto-do-public-data.usa_acs.demographics_soci...\n", " \n", " \n", " 534\n", - " acs_sociodemogr_4bcba275\n", + " acs_sociodemogr_cd142453\n", " Sociodemographics - United States of America (...\n", " The American Community Survey (ACS) is an ongo...\n", " demographics\n", " usa\n", " sociodemographics\n", " usa_acs\n", - " Core-based Statistical Area - United States of...\n", + " Public Use Microdata Area - United States of A...\n", " Shoreline clipped TIGER/Line boundaries. More ...\n", - " 5yrs\n", - " [2009-01-01, 2014-01-01)\n", " yearly\n", + " [2013-01-01, 2014-01-01)\n", + " None\n", " True\n", " eng\n", - " 20092013\n", + " 2013\n", " Demographics\n", " American Community Survey\n", - " carto-do-public-data.carto.geography_usa_cbsa_...\n", + " carto-do-public-data.carto.geography_usa_puma_...\n", " carto-do-public-data.usa_acs.demographics_soci...\n", " \n", " \n", @@ -4619,11 +4619,11 @@ "7 wp_population_c506ad15 \n", "8 wp_population_b2019d83 \n", ".. ... \n", - "530 bls_labor_35c98360 \n", - "531 bls_labor_2c89d72e \n", - "532 bls_labor_2d4bbd19 \n", - "533 bls_labor_933c1897 \n", - "534 acs_sociodemogr_4bcba275 \n", + "527 acs_sociodemogr_bd7ed0dc \n", + "530 acs_sociodemogr_8e66b3d3 \n", + "532 acs_sociodemogr_6347604c \n", + "533 acs_sociodemogr_231a457f \n", + "534 acs_sociodemogr_cd142453 \n", "\n", " name \\\n", "4 Population Mosaics - United States of America ... \n", @@ -4632,10 +4632,10 @@ "7 Population Mosaics - United States of America ... \n", "8 Population Mosaics - United States of America ... \n", ".. ... \n", - "530 Labor - United States of America (County, 1992Q1) \n", - "531 Labor - United States of America (County, 2003Q3) \n", - "532 Labor - United States of America (County, 2002Q3) \n", - "533 Labor - United States of America (County, 2017Q3) \n", + "527 Sociodemographics - United States of America (... \n", + "530 Sociodemographics - United States of America (... \n", + "532 Sociodemographics - United States of America (... \n", + "533 Sociodemographics - United States of America (... \n", "534 Sociodemographics - United States of America (... \n", "\n", " description category_id \\\n", @@ -4645,10 +4645,10 @@ "7 Mosaiced 1km resolution global datasets. The m... demographics \n", "8 Mosaiced 1km resolution global datasets. The m... demographics \n", ".. ... ... \n", - "530 Extract from the Quarterly Census of Emploment... demographics \n", - "531 Extract from the Quarterly Census of Emploment... demographics \n", - "532 Extract from the Quarterly Census of Emploment... demographics \n", - "533 Extract from the Quarterly Census of Emploment... demographics \n", + "527 The American Community Survey (ACS) is an ongo... demographics \n", + "530 The American Community Survey (ACS) is an ongo... demographics \n", + "532 The American Community Survey (ACS) is an ongo... demographics \n", + "533 The American Community Survey (ACS) is an ongo... demographics \n", "534 The American Community Survey (ACS) is an ongo... demographics \n", "\n", " country_id data_source_id provider_id \\\n", @@ -4658,10 +4658,10 @@ "7 usa population worldpop \n", "8 usa population worldpop \n", ".. ... ... ... \n", - "530 usa labor usa_bls \n", - "531 usa labor usa_bls \n", - "532 usa labor usa_bls \n", - "533 usa labor usa_bls \n", + "527 usa sociodemographics usa_acs \n", + "530 usa sociodemographics usa_acs \n", + "532 usa sociodemographics usa_acs \n", + "533 usa sociodemographics usa_acs \n", "534 usa sociodemographics usa_acs \n", "\n", " geography_name \\\n", @@ -4671,11 +4671,11 @@ "7 Grid 1km - United States of America \n", "8 Grid 1km - United States of America \n", ".. ... \n", - "530 County - United States of America (2018) \n", - "531 County - United States of America (2018) \n", - "532 County - United States of America (2018) \n", - "533 County - United States of America (2018) \n", - "534 Core-based Statistical Area - United States of... \n", + "527 Public Use Microdata Area - United States of A... \n", + "530 Census Place - United States of America (2019) \n", + "532 Public Use Microdata Area - United States of A... \n", + "533 Public Use Microdata Area - United States of A... \n", + "534 Public Use Microdata Area - United States of A... \n", "\n", " geography_description temporal_aggregation \\\n", "4 Global grid at aprox. 1-kilometer resolution (... yearly \n", @@ -4684,37 +4684,37 @@ "7 Global grid at aprox. 1-kilometer resolution (... yearly \n", "8 Global grid at aprox. 1-kilometer resolution (... yearly \n", ".. ... ... \n", - "530 Shoreline clipped TIGER/Line boundaries. More ... quarterly \n", - "531 Shoreline clipped TIGER/Line boundaries. More ... quarterly \n", - "532 Shoreline clipped TIGER/Line boundaries. More ... quarterly \n", - "533 Shoreline clipped TIGER/Line boundaries. More ... quarterly \n", - "534 Shoreline clipped TIGER/Line boundaries. More ... 5yrs \n", + "527 Shoreline clipped TIGER/Line boundaries. More ... yearly \n", + "530 Shoreline clipped TIGER/Line boundaries. More ... yearly \n", + "532 Shoreline clipped TIGER/Line boundaries. More ... 3yrs \n", + "533 Shoreline clipped TIGER/Line boundaries. More ... yearly \n", + "534 Shoreline clipped TIGER/Line boundaries. More ... yearly \n", "\n", " time_coverage update_frequency is_public_data lang version \\\n", - "4 [2020-01-01, 2021-01-01) yearly True eng 2020 \n", - "5 [2019-01-01, 2020-01-01) yearly True eng 2019 \n", - "6 [2018-01-01, 2019-01-01) yearly True eng 2018 \n", - "7 [2017-01-01, 2018-01-01) yearly True eng 2017 \n", - "8 [2016-01-01, 2017-01-01) yearly True eng 2016 \n", + "4 [2020-01-01, 2021-01-01) None True eng 2020 \n", + "5 [2019-01-01, 2020-01-01) None True eng 2019 \n", + "6 [2018-01-01, 2019-01-01) None True eng 2018 \n", + "7 [2017-01-01, 2018-01-01) None True eng 2017 \n", + "8 [2016-01-01, 2017-01-01) None True eng 2016 \n", ".. ... ... ... ... ... \n", - "530 [1992-01-01, 1992-04-01) quarterly True eng 1992q1 \n", - "531 [2003-07-01, 2003-10-01) quarterly True eng 2003q3 \n", - "532 [2002-07-01, 2002-10-01) quarterly True eng 2002q3 \n", - "533 [2017-07-01, 2017-10-01) quarterly True eng 2017q3 \n", - "534 [2009-01-01, 2014-01-01) yearly True eng 20092013 \n", - "\n", - " category_name provider_name \\\n", - "4 Demographics WorldPop \n", - "5 Demographics WorldPop \n", - "6 Demographics WorldPop \n", - "7 Demographics WorldPop \n", - "8 Demographics WorldPop \n", - ".. ... ... \n", - "530 Demographics Bureau of Labor Statistics \n", - "531 Demographics Bureau of Labor Statistics \n", - "532 Demographics Bureau of Labor Statistics \n", - "533 Demographics Bureau of Labor Statistics \n", - "534 Demographics American Community Survey \n", + "527 [2016-01-01, 2017-01-01) None True eng 2016 \n", + "530 [2011-01-01, 2012-01-01) None True eng 2011 \n", + "532 [2009-01-01, 2012-01-01) None True eng 20092011 \n", + "533 [2011-01-01, 2012-01-01) None True eng 2011 \n", + "534 [2013-01-01, 2014-01-01) None True eng 2013 \n", + "\n", + " category_name provider_name \\\n", + "4 Demographics WorldPop \n", + "5 Demographics WorldPop \n", + "6 Demographics WorldPop \n", + "7 Demographics WorldPop \n", + "8 Demographics WorldPop \n", + ".. ... ... \n", + "527 Demographics American Community Survey \n", + "530 Demographics American Community Survey \n", + "532 Demographics American Community Survey \n", + "533 Demographics American Community Survey \n", + "534 Demographics American Community Survey \n", "\n", " geography_id \\\n", "4 carto-do-public-data.worldpop.geography_usa_gr... \n", @@ -4723,11 +4723,11 @@ "7 carto-do-public-data.worldpop.geography_usa_gr... \n", "8 carto-do-public-data.worldpop.geography_usa_gr... \n", ".. ... \n", - "530 carto-do-public-data.carto.geography_usa_count... \n", - "531 carto-do-public-data.carto.geography_usa_count... \n", - "532 carto-do-public-data.carto.geography_usa_count... \n", - "533 carto-do-public-data.carto.geography_usa_count... \n", - "534 carto-do-public-data.carto.geography_usa_cbsa_... \n", + "527 carto-do-public-data.carto.geography_usa_puma_... \n", + "530 carto-do-public-data.carto.geography_usa_place... \n", + "532 carto-do-public-data.carto.geography_usa_puma_... \n", + "533 carto-do-public-data.carto.geography_usa_puma_... \n", + "534 carto-do-public-data.carto.geography_usa_puma_... \n", "\n", " id \n", "4 carto-do-public-data.worldpop.demographics_pop... \n", @@ -4736,16 +4736,16 @@ "7 carto-do-public-data.worldpop.demographics_pop... \n", "8 carto-do-public-data.worldpop.demographics_pop... \n", ".. ... \n", - "530 carto-do-public-data.usa_bls.demographics_labo... \n", - "531 carto-do-public-data.usa_bls.demographics_labo... \n", - "532 carto-do-public-data.usa_bls.demographics_labo... \n", - "533 carto-do-public-data.usa_bls.demographics_labo... \n", + "527 carto-do-public-data.usa_acs.demographics_soci... \n", + "530 carto-do-public-data.usa_acs.demographics_soci... \n", + "532 carto-do-public-data.usa_acs.demographics_soci... \n", + "533 carto-do-public-data.usa_acs.demographics_soci... \n", "534 carto-do-public-data.usa_acs.demographics_soci... \n", "\n", "[440 rows x 19 columns]" ] }, - "execution_count": 9, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -4852,7 +4852,7 @@ "68 carto-do-public-data.usa_acs.demographics_soci... " ] }, - "execution_count": 10, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -4909,36 +4909,36 @@ " 0\n", " 0\n", " 900\n", - " MULTIPOLYGON (((-73.96743 40.67345, -73.96683 ...\n", - " 39565.324924\n", + " MULTIPOLYGON (((-73.96811 40.67413, -73.96751 ...\n", + " 48519.041439\n", " \n", " \n", " 1\n", " 1\n", " 900\n", - " MULTIPOLYGON (((-73.97035 40.57749, -73.97009 ...\n", - " 32622.336873\n", + " MULTIPOLYGON (((-73.97155 40.57732, -73.97112 ...\n", + " 36530.582806\n", " \n", " \n", " 2\n", " 2\n", " 900\n", - " MULTIPOLYGON (((-73.99781 40.62418, -73.99755 ...\n", - " 29685.123333\n", + " MULTIPOLYGON (((-73.99833 40.62538, -73.99361 ...\n", + " 38136.981680\n", " \n", " \n", " 3\n", " 3\n", " 900\n", - " MULTIPOLYGON (((-74.03678 40.63431, -74.03618 ...\n", - " 28988.433349\n", + " MULTIPOLYGON (((-74.03764 40.63448, -74.03738 ...\n", + " 35688.646046\n", " \n", " \n", " 4\n", " 4\n", " 900\n", - " MULTIPOLYGON (((-74.00451 40.59723, -74.00391 ...\n", - " 6086.711014\n", + " MULTIPOLYGON (((-74.00519 40.59792, -74.00391 ...\n", + " 9609.119706\n", " \n", " \n", "\n", @@ -4946,21 +4946,21 @@ ], "text/plain": [ " source_id data_range the_geom \\\n", - "0 0 900 MULTIPOLYGON (((-73.96743 40.67345, -73.96683 ... \n", - "1 1 900 MULTIPOLYGON (((-73.97035 40.57749, -73.97009 ... \n", - "2 2 900 MULTIPOLYGON (((-73.99781 40.62418, -73.99755 ... \n", - "3 3 900 MULTIPOLYGON (((-74.03678 40.63431, -74.03618 ... \n", - "4 4 900 MULTIPOLYGON (((-74.00451 40.59723, -74.00391 ... \n", + "0 0 900 MULTIPOLYGON (((-73.96811 40.67413, -73.96751 ... \n", + "1 1 900 MULTIPOLYGON (((-73.97155 40.57732, -73.97112 ... \n", + "2 2 900 MULTIPOLYGON (((-73.99833 40.62538, -73.99361 ... \n", + "3 3 900 MULTIPOLYGON (((-74.03764 40.63448, -74.03738 ... \n", + "4 4 900 MULTIPOLYGON (((-74.00519 40.59792, -74.00391 ... \n", "\n", " total_pop \n", - "0 39565.324924 \n", - "1 32622.336873 \n", - "2 29685.123333 \n", - "3 28988.433349 \n", - "4 6086.711014 " + "0 48519.041439 \n", + "1 36530.582806 \n", + "2 38136.981680 \n", + "3 35688.646046 \n", + "4 9609.119706 " ] }, - "execution_count": 11, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -6246,12 +6246,12 @@ " .addEventListener('ready', () => {\n", " const basecolor = '';\n", " const basemap = 'Positron';\n", - " const bounds = [[-74.0416718, 40.5738831], [-73.8652039, 40.6988525]];\n", + " const bounds = [[-74.043045, 40.5738831], [-73.8638306, 40.6988525]];\n", " const camera = null;\n", " const has_legends = 'true' === 'true';\n", " const is_static = 'None' === 'true';\n", " const layer_selector = 'False' === 'true';\n", - " const layers = [{"credentials": null, "data": "H4sIAIsVyl8C/6VcyY5dtxH9l14rDc4sehsguwDZB0Zg2IohQHELSnthGPr3HN5HsoZbWnRa2kg8r1gcamSR98+n1z++fHz64elvH396/f3rx7++fP788efXTy+/PX14+vej7b9PP/zzz6dPv+BXAa2aAA1fvr58+fj19dP84Z9Pry+vP33+15eXL08/5FFbfc6pjJQHtUTfPjz9+vHlPx9fv/5x/fTR099///z66R8vn//49eL688vL118+/fbT68UYf/7S8/NovSRKH0p4bj2X0vqPHxbQKPXiAjmmDbRI+QB1tBEfQGlFAqWWDVAc4wBlZJ+i1FFpATlUbg8UdnvMmQkylsQjkO2KQx7hsB4jNo9FraE1j6KFJChyHmUtYYsjpwMk6iN5FKnmOjzmKaQwvJWKNfgUofQNKB51ABvOqOrAvmYPIPS0gYy9YaDEttp7ICboI+wFwUz59z3FUjygtTEW0EONZ5vqRBaA1ZdATi26QKybRwe1C2jmZVAib3pTuslbkBxGqR6QMPXqLXoqoXvCIwG1sTWl3NJdcGtMYbdnbH9zAal+c957UDn16rWnkWNnIOQ9vdSZAVr7uDVj9XLazZWYbxmxtCU2EQLRXaBCiBgoNJZAxRRr9IBAXXRFA+q7gB4CU2D9Y3aBQJt5qEkwh40qfQGgLQ5Fm7MtDo8GIWjEw23NBSpWYe0RuFWeoFjbRrA0LgDRyrx7UJO1JFNASACw/MMDWECgGhR5VBF6mTweLJwWGCmR1xVrBqShiZkLCqhAHI7KtGliqwuEVoX2oeOH6reaO7GA4j9xA5irUOQ0fArI4TIvhjmbF0jDEMzZIFkAxnBRwLMEl0LPQ/CYlnG4gBoum0mMNtTsGNaWKWem6FO1PQoKUOIF5CJ4HJtu248TMD2NThvIrbGTg26k1VPOkTzPZIAY26ZQLBQgB9Vg+ZcjbVN/2S2GBu10REFSqEWHxSwbUNvU8KNUnR0XzlorWkswOdVRGwkoLRcBgbYLIoTQlkREIxY4EZK2VlN2dpiizHGDsG77nQoPllII/WbuG1SsjLs3gaesflh4CyTx59u3DyvCjW+LcFNL6RkCTpBrmO9S3xHidtjWdm0H1KRgB/aQYf9prHbKkeVwrFirwtDA7/CawI/1BzBSkMBeQwC5C+VACOJTYI0eQTR4UIvpvn03YMfjloegGDQExd7waaay3HFux8yH0xGFkSTrVtcsoFU1xnvEXyk1mLB7xA8AnZW7PFvgBOoABgkeAsjIecpdAwBAA8kDoHyyqx3BA2ij97v6AaAmRnXsyw3YVs90xWYSQK48XDasZlTHEptpsOm2wDH2tqeeqbntofg9wf71DSCaifcg2gLHk5rd4CDabKwEYskst+ytjbjVjMSlOoLLUQcAxDjjHsBYINJYsq51g2Mho02SQumf4AFXjTDVGZUFzjxgNCMrmgKkgeHoyVgqOaqOEKB5APSabZjsCgpB96iqduwA3YMqtKfasrN/Ftj5FIBApd/jGngKpOnlHjsBqNAatoY1Fq/9WCo43sEKTrmnvNpDLeL3RH0BGSkKa/4owaUQLkANFRqTN8Fc8szATDfXusJFip6QKCwKhEcsBjOt2LNTe3f3S8pjpjd5TDCk+hxTxp94DewdHhM2LD5m31KB4J6VH8hqCy2gJs6I52TGBrDaTFGn93ABJH7V66rAQySPOQxG3kAQ5xBQ4O5TZISRw+OBDg5A4vQATrqtuDghoBRdwSC2DWRxEDGQRfsUAelld0YFEwFF8IB5llecrgiqmYvDnBB0NfIA+OVIXletQlCcmVNDJO5tFEGffYoCtV9AnZM6QMbKLwAelCIDpX+HIiN49+YhKL7LHKnQd4AiDm3kqOC6ostcA6kj11gAouHBwDyoewCIe4oLRKwhM4erpCUl8IJ8cEkpYt0XAFs0PCDARzQebsx18QgliK4kEJrTURw9Nh/I3e0o0lQhZ6UiNI6KR9GzOFSRPGDYORVCIInwfgFFpEKSog6RPAlRiPASnAqJjcXSDtFVmQ7EAyrC2OR1xbKO/Y6COWtHhHxFT58MBcK9pcwRvogPCoQyx9zFYYRQf0uBfeuLR0qcaBJErHVngjPvy9kF4COz05UwY5q5MHx6uIg74hgewFbXdMV22jAvMW3mGmAnETMkpjpuJeYg8vuZ4PsUSCRy9IYrKAxzyuRJiWSuhEFSVORGDDREhtERauE3tRpICqU4kofLWGms7Ab/4nRdeHKt/MhlUltSCMkjD0DoLE6kZ8azeKTYOxuYafXiokhRHHpDMeLaC20/JaBM8Tx87tkx9/dQRQVR+W1BFCZCz9M8F0QIEaz+3yCqPIfckFs/Zo8dCSuYvwAYz+YBdR6tLaD0URnIKTwmmWsNAkCsVDeAjU4HQM/Ja4fS9tVOdYX/sz0icn4sfIaFkABi7QX0sPPZCcCS1OICEdGz01WaDnXzqJlnkWDGMnkAguJN0SEpkQHECXUBiNtdgJD0dgZK3TxgNhMDyP9oAYiZeB4JsVUeHgV+uAEECGKCcBKheQBEaq3IQGrALBDqrI4GBZ4E3Kz/87iSEjtUJqA6JEFbOQkA5G7RA/RI03TgC6hNdAUrsY4Jza7Gfcqb8beTR6BELaVdV9aynBAi1UWAWKtUh0BpBaxQ2e1xHyzM9lD3ESWWvaxM7AIybQ5IJYoPpMIaiWAursp1xrqkA8QR6QCZmMc8cl3HyDlQLz4AbTvtRGWd8KZ5LMjtZaxD5Jn2jO4BsFetMAfqu6c+vZ8zPazkznIvYOyzX0PBmweNKvm+Fab5SI3p5whmaiM1R/ATcv/iKIr5fYEx3QxS48VIiOS2+ddTq8jUk0fBSopgfZ8qXEDPm6IiDuRJdKRQySYnF9CbT4EQL9zyHG2eRGZ0mcBYfAo2miKR02ZWZJHaMIs0+TLlSAtcCrbxIvUzFIY5BCo6M5fM1QQlBdJfQcGeR+95xhZmTzjZhykhRDoR9u+VwkDRd6qhNEw6T6mR4vdQgiB+n8b2wjGU5gPSGEi/rcyH9PTI7kRXs8yzgRJFVz3vXCaDO1s7mOm6nUhuSbj6vuN2bR6x18EPP24BiwqlyptCqQYezx1qgMRwXll5RyAVkNE/JKQORAFnvIicw6Ngb9vhHXc7NKAzEFaRfaZmOZzFhSF8HJagHeHEaY4Y+eN4HAEo2DGAPcgeAB1ZHY3SOAcfY1ckkE/FzjE1ko/N4XC+2qH0xWmnkShaxipwBgD34ATnluJkBobFSSXkIqmsB8uKrLB5FLzehgVCRDFtAbQeXd4zquwebwQT1QeQKEWvq9Jqifd07wbUVNYmIf4QK3JyNMvj5FA3CgFoHjzxPEum3nDzNM+cM4exykMD8UR30m8AIKkOBba+cEkXHYe2AbjdcU+/LUUprWweCGAEBUTAZV7nHR6PgidoePB+WID3Q3clVhcGvKR7hloHDPRIHgUEV1AIHmAhVlcAKSHJ94QhlSRmLjTQAKyzCfIQPSWHxxLMhVUwwDEj3NNldnbpQbDW5kj/XtgvlrbLEOZ2gCOfE6gxbNN5NPbRPnK3Kn4Z7bHutRnjbI258jH1jbcEam3PGTqJDDAiwqD3eBlMcCWIcCsiJQqhlXVhDBJCpXpAjKnTbdmvq2Yxeu0k0rfpmNY5CfYpxHjb71v7FhAAsXL1mUXKAkcIbVd8eINflOLYMEQkkURXRzUA1OwYVrQj8ynOcdko4g4E2yPbvg0Y2ueJEpu8Xtbh5SzHCiD2eIAqDDQC28W4zlNJPgVdARDGLBwcH5qqdlGv0d3MNLiutSu1iaNf6Fq/r5AoyuglRVaQqrc74tgZ9omaC7C0XifYRJsH5K17R9uEveWqOlUEnbSAtE9fDAX1JCkOD4JV5xq5AhBoDo9HJ3F7TBzRWyC2uoE2ildcmjdER/OASqGJcgalFSFThdfMTkWBiqx4yfYmJFOyKEUUTLjmZAgKBIQcDlyA0O0sCOAlqgxIQU/7LFU7VQbKs0jlVBkoh8o19SP7pvmoiu5HqJbmLCqlFji1VUq1CID1GlJSKTqGgGLbJxq6LmAoTmACHgjeyz0wAZBFxHniEksgAM2CSw8wa6LQr4Cootdj5yjAFJNjGQ0Fn84b5gLQw2XjaxZXAkRexd5sLB/OK1ETR/BKxmW7Uq+p9csZEZLWKJIbrMIGEI1xAAeztCoJAtCOkOZN3XYLcKTOm/ZjPbRrFhZKpXQwdogaBED7sjpBhJuIlXoL29IWcdQcYl25vYkXboGECnHa20KcOJ6pQAKgtfOaWij//7UO2NG+bobCd+STCtJ8qrDMmgHKLEouAOFcZqCVZb8qtkwQzP857XArfkeIN9cZjAUQyayeZimIgYQ4pblAX4ec87p/99oRGx+3Pk0qbdb4eRVAWndxsS4Ij7h9ngYtYMbHHtASnUcckFUEV4v3vCLMALZzA30WSRloY7djRbx2eKfgdkRw2IVZ77v+M7MRDEQ71iM6DAZG1Lk9kvf7Nt1qdxjMa8p5AwGbeAAswDpMtEDJ61DUdNXnvUCP+XxEQy6AtXG7qvOczFknBdTodzW9kjsqDENQIPtcil+hrD15gBIc2ZUStXlpfR2Kwj8F0RWS5GWNLMDzUNI878WvapWWf0kxK3jNm7nSSQUI7ZY9YdGHxxoO1F3zMKr4PRSGnHaEB+sAvs5qf/aWSTEQC67be98MdEdwEXsjFOcR62mHpeoMlLHOuessELDeTfu/gciHYTRfIX2HglVY8ZiGYWsShIOnIe2NAdik6a4koJgfW1cGe2jVDMp+t6WImmJh61GgIsMDIEFxeD01GJbqjajNV23OHvU+wxTP8PfatvvSlh+uvrteB/MLyXN41kMq193fdpkgISK7EpkxT9t6SO84nSgIKtZrTnF/bAJh7BxU3DgzAN+xuAA6lwn5VtsFpEG3C3KzMIB47dyckxQZcfi5B3cueFxAGPteogamRLhdYU/y7dqeLnyIO5xXuYJ2hmiqVpCGkF2KcC766QIYbOmuR+qSGdKJ7hGIkpIujIkilC6M5dT2oFSBT1SzTDuXv3RPKVTqTjlSlvE08P1qHVSMnKJcmukLeQVavqphKXLczE1lkyl0kfR7lU0J8J1PfR1Eb6y43KH3SdzhENeGLCDFTdZ0lYCKeyJanySFknVZN1aqiZVrtbkA16b5JtVVzUZ+M+zdKw2I21q6K3G/S99eiSO4zXxR7OIAfRr2atkFhLQ58J1PXawXV9dUdV9cgrtuA8x7ifbanAUwEMGihtrsDTx9H8AC5z6AuKdpFopv+ZkVMcC5KGCGC1ceqgfwfQDTFZf9xd1DrTXiDqXWTHGNUVfeDcBFfN1VjrXk7jAXJXkD4D+nq3O5Uls3JLxV8GB7GCEwje09MmnaQM41OabVUmxbbFhwkd0Cp8gOXil4fsACx3PMgycxP/Y1ZlDsncQ9VF2WN9vBjs4sLoXWPHnLCCGCJ2/CmWqFEu5Xa6Dw5LHPnNQJClhnRAiBWI39iWwfaT8xvaKUWDdfvmp+ATWsT0Wcq+lXc+v7lUKovYqfUx32UrwbBqkAjd4WoLWS+tyeRIRwPsf2niczaSYa62w/1+EdoOpyCdcmZO1AXNDWNQ5VhRA1DsLAVz8Nq8hH7rvUhJA2NedY2AB8kDzwVxQ5RNGiz+zIufmOf5MEuDaBXDt5lQYD8DG56YoP1ufjg+6dxA+kHlzLFmf3luI8UTA8+JWHBc5LhHmozFVj8XZhIMUYLqBXN84PiCxgBgwMlHhqURoIfTPX+xr6utlr20PZBKpKhZhpWQ8IeZDtIS6HoctsWL/tMFRdDqn2jst0e2s79NOFv45QcEuhqi32WY/2Cp5Ik3Ygp+tdkoJrqoYHF2ENwGVb0xUf6Grm4ghYU4hD44sHVLE4hTAFyEKY7EqVtSRzVdaSFHwmfvFA8lWc4/X5pY7snbvD9ifyTuo77QhWF8iEiFgg7xyEkHyLQcGQbN66CMeqYQB+GaW7Enppy3ZHk79fz9NdyQqgAkSVUXclKnoG4Iqe7kqU9AzAZVRdHGQ7qauJbFgtwTHFhgU/AzSLy5VoQ8Gla8ODyBnR8THmx/z+CL1FUYtlAsP2vGSCgxffHpCALiLxK0pIVmUVG+fjRVr1RCFTFa3FOyZd5hYEqi4uXkTpSroCpAERJVFtckRJVNz8MDca9H0NflwFS9STACDl0buWkea7Yy8AuUUmKmYab3xmjKz2eZ6ghzrjr/CeZ8a1z4DdXl3VH8CBCxcWrLYQU7dvASxASbxrnw9g1muDKO4XyPbzCkF/xifDZXufRJAPHfTniCxwPmAknrVY4Lyl0B8wEs8y9CfKxLMWQ8GPVMyo+K2IYa4p+NNN4hWJ/kKTBc63y0xX/KUpw5w/c6UB8XWxPOt7zhfBxFsY/XExA9D5zo3uaZbFPc78dS8LnO+B6dmVtr+fpzepzFKefTpzteddWxOvmCYAX1K6fUJ1AXGX/w0wBcmTnPm5pOhJpwT4JdgF5LBeHmrNwEz3jQjxDmcCyFeXVTdAQNZSHeUriFWX3RNXzQ2FUvCCMOEA5+3ONaq4vwog3u4YCr4xb4bLj3rMqAyQttHVXWU40n2XPnXxfZEM3rE5o8pExaeY5U6PuaTgtwIXj5r3Wz5+dnANN5S9JPzUyExQAzGVvee6q1jH4ZFpuKurAbEfhgdTBLgbdz/Ocws7WtXOuzHvbWQH4PccuqM0P8GXHc4WOGMVT0b07GA1xOUfSUFpCApeQehP5TtMkjm/UDIU/PDFMOfD98uQ1POeVgOIJPfTXD6Vv4Bt0vWHGES7+tzC/LrP6M7nFtjmmXY2kvqLDsKsGtbHDtv2Y7fFuyztAsw6sc/QSy68TILFYx7is4UW2F/kMduqAHEqInyieIRnACVSwr0qqRVjUuKv2qWCSQeuVFKM1QLg7qm9DCs0DxHsGIDDo/M2ysRfSuv5E1NmeuebVJaAv3FoWAsg1iY+dbQ/eyXfUumPImpzzt+t1UZ7fo2pJsf5IDevexI6UL1FsFds/eO3/wGrLvx8AFoAAA==", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "v18db55", "title": "Total Population"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "color", "title": "Total Population", "type": "color-continuous", "variable": null}], "map_index": 0, "options": {"dateColumns": []}, "source": "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", "title": "Total Population", "type": "GeoJSON", "viz": "@v18db55: prop(\\u0027total_pop\\u0027)\\ncolor: opacity(ramp(linear(prop(\\u0027total_pop\\u0027), globalMIN(prop(\\u0027total_pop\\u0027)), globalMAX(prop(\\u0027total_pop\\u0027))), bluyl), 0.9)\\nfilter: 1\\nstrokeColor: opacity(#2c2c2c,ramp(linear(zoom(),2,18),[0.2,0.6]))\\nstrokeWidth: ramp(linear(zoom(),2,18),[0.5,1])\\n", "widgets": []}, {"credentials": null, "data": "H4sIAIsVyl8C/52TvW7DMAyE30WzK0gUxZ+sBTp3LzIEiVoYSO3AdQoEgd+9suPBGVmNBOnvfDze3Xi7FLdzb+UwXofy2p/P5Ti2feca9/mo/bjdx921p9oVavV5oBYuQ38pw9jOjXc3lN/SXWtHTBADBs8MU+O+Sv9dxuE2t6xfeO/bbqzzx74fTm13GBfSCyevmZGaOkscA+ynqVn50cIHkiDBYxQznyLAzM/MShs+mPgoMSVPqma+KMvy/1ERN/xk4UfJHKB6SDY++gCcF3yCJ/vRhEdB4Gp/0OWJWUUIuriQtUZpIyPbZGAg8kTZvAUFiosNIqgbPln4oV6BpGqphuVFqwzhEB/byCnmjQw2yFCoWWCfEtjDkFJMaxiBN3wx8Jkya/JIaxj+cRKYl5MkfTJBLSJQIZJPUcxLUBSG9SRg5u+nP/xeZSY7BQAA", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "vabf72c", "title": "Annual Revenue ($)"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "width", "title": "Annual Revenue ($)", "type": "size-continuous", "variable": "size_value"}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAIsVyl8C/52TvW7DMAyE30WzK0gUxZ+sBTp3LzIEiVoYSO3AdQoEgd+9suPBGVmNBOnvfDze3Xi7FLdzb+UwXofy2p/P5Ti2feca9/mo/bjdx921p9oVavV5oBYuQ38pw9jOjXc3lN/SXWtHTBADBs8MU+O+Sv9dxuE2t6xfeO/bbqzzx74fTm13GBfSCyevmZGaOkscA+ynqVn50cIHkiDBYxQznyLAzM/MShs+mPgoMSVPqma+KMvy/1ERN/xk4UfJHKB6SDY++gCcF3yCJ/vRhEdB4Gp/0OWJWUUIuriQtUZpIyPbZGAg8kTZvAUFiosNIqgbPln4oV6BpGqphuVFqwzhEB/byCnmjQw2yFCoWWCfEtjDkFJMaxiBN3wx8Jkya/JIaxj+cRKYl5MkfTJBLSJQIZJPUcxLUBSG9SRg5u+nP/xeZSY7BQAA", "title": "Annual Revenue ($)", "type": "GeoJSON", "viz": "@vabf72c: prop(\\u0027revenue\\u0027)\\n@size_value: ramp(linear(prop(\\u0027revenue\\u0027), globalMIN(prop(\\u0027revenue\\u0027)), globalMAX(prop(\\u0027revenue\\u0027))), [10, 40])\\ncolor: opacity(#FFB927, 0.8)\\nfilter: 1\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(sqrt(prop(\\u0027revenue\\u0027)), sqrt(globalMIN(prop(\\u0027revenue\\u0027))), sqrt(globalMAX(prop(\\u0027revenue\\u0027)))), [10, 40])\\n", "widgets": []}];\n", + " const layers = [{"credentials": null, "data": "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", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "v18db55", "title": "Total Population"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "color", "title": "Total Population", "type": "color-continuous", "variable": null}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAOKfXWAC/6VcTcudOXL9L+/aeVFJJanU24HsAtmHITQzzmBwxsbxLJqm/3uO7pVUVboViMc2DW2dq9JXqb71/P72/bevH99+efvXj79+/8e3j3/68vnzx798//Tl728f3v7r2fY/b7/8x+9vn/6KXyW0+g5o+Prty9eP375/mj/8/e37l++/fv7Pr1++vv3CUmm8JyYuI7cqqf3x4e1vH7/898fv3357/PZJ6t/+8fn7p3//8vm3vz2G/cuXL9/++unvv35/jIw//9LL+2hCxOMDp/fWmUopf/6wgF6Jo/Y2xqAFlFS1vdXan+21FB4KEKcN1NTaASpXpgjgUfYQtXXRsctIG2g9SVagDM4LkD508Ix/5ahHrqWudbfSzHQzjVwjgIRjUtiecPA6RksjBJjbs72nSlXbKeUNYEXaQVLPaw+B6Ni19zzKE5AkhlTPxOv8BGvVHq3m3kMg0R5DOLMcoOLMNyksRHtg6mcMHJn2YJxU2APr7hINbgCcedN1cMYGR3tVOlg32twMdpMIIBl5BAdYCZu1D5BGCQHHoXPhYzEJ4zoogCmOdYLcWFm3JuptkSpgpQPwIOzWAnI/65tbONZxpJqFFch5LS8lKkF7wxKaBISaYMsMgKE30DjRASSLhO2S1gY24SY61yFlAxAKCtRUuG8gN51UJSA1BM7OXqT09MAJosuoOZe1szdQ+yY1pZkyArZn8VRrCfdBAdzXGgKgtrYEOyIRe97AYWiI6FFaCOTURnBp2jyaEdy/xoWlBTcWY6dagjveihQzuEqFGzhyBEKv5UDwQMaSGVtFVcujm7GPbGu5mauksrBlbkllemrcWwQQtRxQMpLbr9oBdp8a4VouYIqNGMDWjIiUYwTMI+eIp4wG8gztADCSKsyCY5LgNhn114awMnSro231lwhWgKrYQnnJW8pkAVXWNCCCAu2eU1chAlmdtrK+gE5bvefMOlkR6Ut85d6i5jI53gCJluQsOADT4+gSb2+8GCj488cfH5bpRD9kOhWcf3qvkG+pCuNK/4TlhP1geewtLk+hdmbcCUJ2LIChgQ6Qpm5bgBTSHolLLiGQQkptdD6UPFA7P9slQVhH7U2G7vrgtEceObEB1s2YMpTNAOdgIRpSyzEApVhfOacK5WZZZ/MaAC4qdA5z3u2HmwE0KPlX2xNH24oBKm6yLGCAk17vWBXIO9OD69g9IIV7f72uVSqM71eJgPYirDcm47w3ABn+Kgnv9iU4Lzoqaf3A+Jf01Q5hN7RDx00P24u0YGUV7JfX7nGpZuSjRuoUQ7m/Gn43cHQYgES636pAsd8lmzGOGfe4lSMGCKbNq5K+uEDV+sVouPODa8CaBvDXouaxjCkA1Lm9WiHXTVVT8ZIGFpiqMiQFXcf91aCpHcTMGMegwWWGMORoHZALo7+ywtWOY1vig63dLr2OJQ04VTOlkfHDJ1AE61YBlaEfQ0BlnSNlpWNNYgCYJhLtR88l7zHcDkIRlacBO7eJ9ZSg62DPhKL5ltlOmeQfUyZCpb1DqkCvP8TATyiTaUAvfQnTw/hxsBzhd4QAXOEN1Ko7P49KNinwtPbAdpUFgKhoD+zKHuMCUjljOFL41RnDDQ4bo0TrEHgPrUeA4FR6QEoEzjsHg08npnAwXQzAT3Z/ASCiKSJVQUyiwfEPqRHAYNoFQB8YAF5W2UCv6j5D3sHKj4DcYeVHpDLBrI2mC+e0RMxge2CfTQ+IWlk9YO+oFe0A6kMiUnAR4sEhwikEaDqPESkocrXp7OAEC2dEACS1OtwwBOgAnAwpGL5rdwmcISEAuaH+syFFkKhq4przoDJd3eAEqXTj5EFRw3YPgcNXFynlRGLcR+0BU2Xx1QVAJK9rQAU7HV0DKsk4LyIStY6y7O6LDPjr0Md6JLjKfnHm8l89VFz4MYyA8ZOCAqQxIqDAgxsRqQK9m6PBGZ5PCwFum1SuxuEePPoeHBytTt609QqFAKwEikj1BDUarcMCbhMNKXfeOA5c4QVU40g6AFutMrfXugEYkRaAJ7qOFuZQDQEoTnULLakOjjRAps0+EjbOAzsA7vFyL3HVxJCB3bF3Fu4GRQCsJeMWzqu0glSZem8GGHltYMY0VIaAP3e8K8MZ4BCAaFBBPFm9LEFcc1JZOC9f40j5vqhrZ0eUH7MjcPPlvXGD+0WgN/5ZO4LfU+lwf55rhNvdl6n7AArE0AJkm9MTaGkLt4JDaXSAylscFvzt2oNli/UbyCNtYFr8B4BTsCaFpZqxcf1XO2w5MzQM3bKBul2YBwC/fQOwgE+PjENcYu8GYAxtYJCOjaFhlz4BGCfLh5mATJX/BAbs0DN47uCOHAENs80RKfxwMRasiTFMj1SfJu0NQE0+GY6nLD3N4LGxmuHu6wDwQJ7u+w1gN3sJCEHBrjAO5FKisN2tTQldM4UhviJFRXJtFAF+x80Y/oyor2Db3Z5XSMhzAWyGnjeQKocALhXlA6Sxw1ql0o5vAoDNAKm8rgUVC7QdOYNxkykEMtRUUwDe8hoc4m8oIFA0i6FgDViAdgKs4LoZAE7nnlVK2395ADieJ6flmVIoQY8sMCY4WGBuIyuQE86z32ap36urxzkO3ITtTLrjw/q3V/o4770f1++VpTJMySEBNxv73bH/1X5uy0WIZ/7stqwnUNNyJW9AL6Sx9x9AbfXF5H5Ig1FEIgAuQpFbm3iJY2xxL6Pg0A4LHKlmTO4pB2FMZAoBkU4BKSM5M6ed/LqBoxUvUm4dsCO59GCv7KzcOdkebtvt4I4JoV65cgQUkC4Bd4ITSg640LRDIJg5QfHtOeG+FFViRHtKMLG5B2rvAiqWUYK7ZzSov61WtSbpKkMgtdpypbyogGrusgEIWyUF86rmCDAKH9dtBWofQM/LUcUuNwNIatsSKJRUFkK+b2fYy8LJ9rkH0vPVDHH2Ef+QfTTDpe+w8CDqcRtK/QnzaGZnn4deYftTPfsLKz09s7AvQF4JXQyOszr7CwGQeAMNIkqBWhYlWKgytB2HuAHBgAeg1pd5lBJjHgrgHEoEpC0W8BvuWdu57xGgctRWHiumbX//aG/0OrI3lWEdwo4O7PQL6GB9ikipS3ENfvwZux/OYcNZdA0Vu3bIMHUecDOfPmGdTNLLq4dXZ7VJ5giAkVIlIlUy/l89VRhYqwfYoAdRNQC4AjXoga1hzY1p5A4AgblfY30VfAOH/dW3vXvolggkDOdggTLzKYFD+gLsc7qne5w5LLAWM8Zxzeq8MQYYue8eGSpXXvntBdhJF8jF1GvA0JBhVV4uwP17+JSrHbaZaS9p1SHYY30AvexbXLAfR3YnTn33YGyOAhVG5gKwG6kr0HcQHhIr2x6jrXi+4cILgP+jAgHHn/i6AI92XLgRCakXsebEbf3BHGlJ/V2elCp24WfkLVTE8oygq7smioyAuQD19yE92dx+lSMwvKxY0BDLYJPBNFEc3w4DZEWQLkJ15hEXAHM8BPxkocf3nGCEdQNQpRoBGoy6lqfhq2tWGvCCa0mGlIbIZs2TATSohgmSESMahruBE7i7SKVldMB/LzlqthtrqBSbE4BZuLeVxBDXdr8Vh7rb7B3WvFuzrICqpyK4jSu44IfF5uYmwTGb9MENnKDtRUrDvP6YTfpgwMszs6rTTXwCqYvmKGVWdS5SiZlMwqFtO05wtC0Gchk1SFHAgje1GlK4H6Bs99gHuAVmZgsB8K1m+2fqc61jSoo+gpi/1Fa4BVkCrJQ0i2d7PGJgQTxeyqAooSIFxnMJUjAXYHbEUdJNFzCFZlrNMd3AOViBr0qGR7CIDUCw94CrLqDDe1oA7EQJAv6SK3MPAv4wyHt0rX07XF3a7VCM/GqZwEcDD1MgOYTa9mQe0gnqNIfAtpcAVJO0NRIQukxMsFWFqUyPkQI5fgNH8l+kNIwtabrKEeCnq1bqtSUaTfbnahSV5ynbw7GIMZEhjzRTZdfn2jWu7/nfATZcbQi5m2SX7QGNx0vFGZdA2/rbapc9K8y1B7bwjHGAp6pPZ4wjEZyzIrNG0ng3VPcQnfoIvBvp0DDGGGy8JwsOsSPo0PA8+qtZiXaI1BwtwslU7WCEsJuSkdp+DYOyiY46ADJAKcF6LFtl1GSHAKuWW8OFNpQz7toPGXcw09+hwOCx5A5TtPI/X7MAMrAUnvIFpPJx+WTW6S3NdAHwgJeor/PxQlYAHsNT8NTZRYGMW7bGqB3/KdBX9BJGsaSwHfa8ITTLqp5AZ+icA9CMYS0AAlcp0a79hpbHrE47XIzVPo92M5s06J8VOKqzLpgUgETZQIfRc4A+fbYQ4LJSEDPkoWO3nsaKsMHFyKI92iyBWQB8Y+0Bl3IlLa4etdPi6WsM2BUyonXwrGVaABwcinpA8JgeZgy36WZW4Miq5z1LevfK2ywNiADHCLO6Om1gOnEK5FRGBJjpOmab5cR7VrB3T/zEA5ZvZ51x3VcAumlEewVbuIQA7NWjrR2pGdMt0eDgN6VUYE+sDlC8HP0+jRoue+ayONooiKfUo631gDkMTwqcuw88zboLZdzcyga6mNl2uDdhD5nhtmcGa9Y69uA6QSsS602GVRi2n4vsCZmbz0NtW7TDSOhBe84c0lHhBRNZo0xW3GFXYKcFApKnxNIecLiXFXkBbRZ8R6Rm1laCyT5ejQRH1Dv4dJ3dnMXhsy5peweeAadUXBasZ1kLOCbvUGVcgmsBsyAt3+vSDC+6xCm5/kNKbi63vfdp3z1MDio/EcLAefI6dlPE9ADoVLRpZcIESHinpbQy4QHUtOvTYGIaALp/99CaqweQx64281kbWJ/reG+AKeW7rsvnA650jmYQfCKrtFJ3XuPqcUoGTLWZT19cwCkAuPI/mpz5f6Z/ci6JI0o2W+WTUj+erTKAG5xySlFGE3JY9nR9CnSgD0WA9LGn65OjWn1wpWUN8H/mG92m2wyly+yZQoYL0EKGK0NpsqCO3SzgEpGm9AFWRzKzquCrDXAzY0C77eyvlhF6YD56qUEyl0wOedan3RVMD6CtWHKbBQAW2BxFsCQLB9loU0B4A0ns2IeSVm659PV8slspWtgF9LTO4aKkaWpTA+a3+wbOkV6kILIOcArQPGua0jvPzKbIzV+YGziXkrLUlF8LfwjGtGk/8oCgQaQFudcL0NzrLBlvIxBFRLRfuvlMKqXRzGTnu8mwh0rOa7aaSb2WB0W+AS3/nADc6ibBMUE+8h5Di1IfQJdNyrGnUSbKgUb10EhGVcEWWfIpaRqRwa5LoqSqyRLOs97/rs4NVaFT0vJjShrCKb3DacG+yYBg/pnq+bkxUahfA11X7Jxg5C1nm+HqlyAmXWeAXWPS+7nqfNejyTGtqh29JNO+wwWwa0aOgtX+5yZYjb86rgkG3sCJHl6kTBTbD67FyhdgQs99+gwaT4XLtrZPZogtiMBO1zHXIGR79dAg70xMaq5QaD65jhao9dvw40fWxx1Ye+khUHYxycyr6eDzEcxSz2C0oW9UpOTdwXHBfEa8h3CJj95wTTkCcGP2EFw1oNShRSXKWnXI8R4lG2wPl9CwQ7hkg52Uxpoey6C8x7iAxpmC9ATs823I+PQEPINt+kC9kr7GwnnvLXRpiz6fBgURNnN6PmthOrikRZetpnzOwszI5ywccOKKnpIGIt0SrhxHqrvU6AIo9Z2xgAFjsgP6tODKitjkhw2nmkt5Aye1dJHSZNQ1uL4guIFBh5SN/hpx5NMiO/zqkyhH1LkfjwQ11KPwtb4fuKLRpodPEelThGvNBnBLsykOxzU2xYGbY4HzOgrzGCZWrO+psF3ZAppnhYmhLG6eZvnrZQGfSC7wo3qY5J0v3CMFdik2p3DHjz5X61C40+/EzYaN+RMKt+Iq7Rqy0s3VOA8LbUGYfXtqy9L9BwmwyYNDQEt53WtVW6/uv4Zgqs/99xNM+bn/4oKpP7+Bap/QMjTZSzW5/xQKPPBsHteaHlob7r8cUWBTRA9fTYm2/2SGb9dPjswPfZgR9JMjWgP++FpHW4Votmjcfffjau/9pZb80Ywl9GBg88URvzT9RIkpMvftbvMgT/b7C7/dXOtOaJmS8QmA/VZW7gImT1BwpPMYVj7ScwfPmuLVo0JwGoB2ztOzJs8PJowQyDuvWuoMyiqAjc4B+zsA5t2ISLmbx7CXVlYQXhSruHXAKeu8pquV7ADgSm6pegEiO9NsSkcfwPwOzgKy+VyABbQ89SJFyagZO7jWxl5bcgF1C0/slH5AxLWf8vprD7W83g9hCnZ9D1Pi68fQKmK/t6bs+AI0IvQAYFjVu7D5cX7YkejFKbz2PuQuf38AfZcl+Xew86soxCEwRuOIFNy8PYbGqR4AzACKAPhzMSm9zP5VqxEX/q2t+UCRf36lgupuPx8ouijBCODohbMD7ONcS8qvD1bxEre4AmTHMAC0EUdjeF6YUNhDv6fkxzDfU/LcY5TGBaiauUjpd4j8rBwg9rsEhhQMFvM1Af06En6hBSim3d8zM0RJJBIpS99hftuBghGmvUHBhTXmww2cDx15SvtLCdeMTLOVOea7SKZQ338XybwCcp9QuIQqesiprreC+9XIelh/f/7jfwGuM9zNXlAAAA==", "title": "Total Population", "type": "GeoJSON", "viz": "@v18db55: prop(\\u0027total_pop\\u0027)\\ncolor: opacity(ramp(linear(prop(\\u0027total_pop\\u0027), globalMIN(prop(\\u0027total_pop\\u0027)), globalMAX(prop(\\u0027total_pop\\u0027))), bluyl), 0.9)\\nfilter: 1\\nstrokeColor: opacity(#2c2c2c,ramp(linear(zoom(),2,18),[0.2,0.6]))\\nstrokeWidth: ramp(linear(zoom(),2,18),[0.5,1])\\n", "widgets": []}, {"credentials": null, "data": "H4sIAOKfXWAC/5XTTWvDMAwG4P/ic2asD0t2r4Wddx89lNYbgS4pWTooJf99TppDetRVyHnQK+Xhxvu1uJ17L8fxNpR9f7mU09j2nWvc17P263afD9eea1eo1dcHtXAd+msZxnZufLih/JXuVjuAEAIHr4pT475L/1PG4T63rF/46NturO9PfT+c2+44LtKbks9RWZr6VhQCHqapWX2w+CgppOAZktkXQJz9qJpl46PJ5wREXnI2+ylrWuaHzLzxyeJDihqwZig2n31AjQtP+BI/m3hOjFrjBzMfQl7Gj7ne0MaPNp+DiBeJ5vgzCizzp8R544vFD/X8E9UszetPGuCZfySIG18Nfsa6ffVEaF8/EdB6fqgbPxl8laiZPAvYr5/j8vdJfpk+W3TOCOIJkp3npLheP87+YfoHPW7k4CYFAAA=", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "vabf72c", "title": "Annual Revenue ($)"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "width", "title": "Annual Revenue ($)", "type": "size-continuous", "variable": "size_value"}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAOKfXWAC/5XTTWvDMAwG4P/ic2asD0t2r4Wddx89lNYbgS4pWTooJf99TppDetRVyHnQK+Xhxvu1uJ17L8fxNpR9f7mU09j2nWvc17P263afD9eea1eo1dcHtXAd+msZxnZufLih/JXuVjuAEAIHr4pT475L/1PG4T63rF/46NturO9PfT+c2+44LtKbks9RWZr6VhQCHqapWX2w+CgppOAZktkXQJz9qJpl46PJ5wREXnI2+ylrWuaHzLzxyeJDihqwZig2n31AjQtP+BI/m3hOjFrjBzMfQl7Gj7ne0MaPNp+DiBeJ5vgzCizzp8R544vFD/X8E9UszetPGuCZfySIG18Nfsa6ffVEaF8/EdB6fqgbPxl8laiZPAvYr5/j8vdJfpk+W3TOCOIJkp3npLheP87+YfoHPW7k4CYFAAA=", "title": "Annual Revenue ($)", "type": "GeoJSON", "viz": "@vabf72c: prop(\\u0027revenue\\u0027)\\n@size_value: ramp(linear(prop(\\u0027revenue\\u0027), globalMIN(prop(\\u0027revenue\\u0027)), globalMAX(prop(\\u0027revenue\\u0027))), [10, 40])\\ncolor: opacity(#FFB927, 0.8)\\nfilter: 1\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(sqrt(prop(\\u0027revenue\\u0027)), sqrt(globalMIN(prop(\\u0027revenue\\u0027))), sqrt(globalMAX(prop(\\u0027revenue\\u0027)))), [10, 40])\\n", "widgets": []}];\n", " const mapboxtoken = '';\n", " const show_info = 'None' === 'true';\n", "\n", @@ -6275,10 +6275,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 12, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -7622,12 +7622,12 @@ " .addEventListener('ready', () => {\n", " const basecolor = '';\n", " const basemap = 'Positron';\n", - " const bounds = [[-74.0416718, 40.5738831], [-73.8652039, 40.6988525]];\n", + " const bounds = [[-74.043045, 40.5738831], [-73.8638306, 40.6988525]];\n", " const camera = null;\n", " const has_legends = 'true' === 'true';\n", " const is_static = 'None' === 'true';\n", " const layer_selector = 'False' === 'true';\n", - " const layers = [{"credentials": null, "data": "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", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "v18db55", "title": "Total Population"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "color", "title": "Total Population", "type": "color-continuous", "variable": null}], "map_index": 0, "options": {"dateColumns": []}, "source": "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", "title": "Total Population", "type": "GeoJSON", "viz": "@v18db55: prop(\\u0027total_pop\\u0027)\\ncolor: opacity(ramp(linear(prop(\\u0027total_pop\\u0027), globalMIN(prop(\\u0027total_pop\\u0027)), globalMAX(prop(\\u0027total_pop\\u0027))), bluyl), 0.7)\\nfilter: 1\\nstrokeColor: opacity(#2c2c2c,ramp(linear(zoom(),2,18),[0.2,0.6]))\\nstrokeWidth: 0\\n", "widgets": [{"description": "", "footer": "", "has_bridge": true, "options": {"autoplay": true, "buckets": 20, "format": null, "readOnly": false, "weight": 1}, "prop": "", "title": "Total Population", "type": "histogram", "value": "total_pop", "variable_name": "v18db55"}]}, {"credentials": null, "data": "H4sIAIsVyl8C/52TvW7DMAyE30WzK0gUxZ+sBTp3LzIEiVoYSO3AdQoEgd+9suPBGVmNBOnvfDze3Xi7FLdzb+UwXofy2p/P5Ti2feca9/mo/bjdx921p9oVavV5oBYuQ38pw9jOjXc3lN/SXWtHTBADBs8MU+O+Sv9dxuE2t6xfeO/bbqzzx74fTm13GBfSCyevmZGaOkscA+ynqVn50cIHkiDBYxQznyLAzM/MShs+mPgoMSVPqma+KMvy/1ERN/xk4UfJHKB6SDY++gCcF3yCJ/vRhEdB4Gp/0OWJWUUIuriQtUZpIyPbZGAg8kTZvAUFiosNIqgbPln4oV6BpGqphuVFqwzhEB/byCnmjQw2yFCoWWCfEtjDkFJMaxiBN3wx8Jkya/JIaxj+cRKYl5MkfTJBLSJQIZJPUcxLUBSG9SRg5u+nP/xeZSY7BQAA", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "vabf72c", "title": "Annual Revenue ($)"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "width", "title": "Annual Revenue ($)", "type": "size-continuous", "variable": "size_value"}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAIsVyl8C/52TvW7DMAyE30WzK0gUxZ+sBTp3LzIEiVoYSO3AdQoEgd+9suPBGVmNBOnvfDze3Xi7FLdzb+UwXofy2p/P5Ti2feca9/mo/bjdx921p9oVavV5oBYuQ38pw9jOjXc3lN/SXWtHTBADBs8MU+O+Sv9dxuE2t6xfeO/bbqzzx74fTm13GBfSCyevmZGaOkscA+ynqVn50cIHkiDBYxQznyLAzM/MShs+mPgoMSVPqma+KMvy/1ERN/xk4UfJHKB6SDY++gCcF3yCJ/vRhEdB4Gp/0OWJWUUIuriQtUZpIyPbZGAg8kTZvAUFiosNIqgbPln4oV6BpGqphuVFqwzhEB/byCnmjQw2yFCoWWCfEtjDkFJMaxiBN3wx8Jkya/JIaxj+cRKYl5MkfTJBLSJQIZJPUcxLUBSG9SRg5u+nP/xeZSY7BQAA", "title": "Annual Revenue ($)", "type": "GeoJSON", "viz": "@vabf72c: prop(\\u0027revenue\\u0027)\\n@size_value: ramp(linear(prop(\\u0027revenue\\u0027), globalMIN(prop(\\u0027revenue\\u0027)), globalMAX(prop(\\u0027revenue\\u0027))), [10, 40])\\ncolor: opacity(#FFB927, 0.8)\\nfilter: 1\\nstrokeColor: white\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(sqrt(prop(\\u0027revenue\\u0027)), sqrt(globalMIN(prop(\\u0027revenue\\u0027))), sqrt(globalMAX(prop(\\u0027revenue\\u0027)))), [10, 40])\\n", "widgets": [{"description": "", "footer": "", "has_bridge": true, "options": {"autoplay": true, "buckets": 20, "format": null, "readOnly": false, "weight": 1}, "prop": "", "title": "Annual Revenue ($)", "type": "histogram", "value": "revenue", "variable_name": "vabf72c"}]}];\n", + " const layers = [{"credentials": null, "data": "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", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "v18db55", "title": "Total Population"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "color", "title": "Total Population", "type": "color-continuous", "variable": null}], "map_index": 0, "options": {"dateColumns": []}, "source": "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", "title": "Total Population", "type": "GeoJSON", "viz": "@v18db55: prop(\\u0027total_pop\\u0027)\\ncolor: opacity(ramp(linear(prop(\\u0027total_pop\\u0027), globalMIN(prop(\\u0027total_pop\\u0027)), globalMAX(prop(\\u0027total_pop\\u0027))), bluyl), 0.7)\\nfilter: 1\\nstrokeColor: opacity(#2c2c2c,ramp(linear(zoom(),2,18),[0.2,0.6]))\\nstrokeWidth: 0\\n", "widgets": [{"description": "", "footer": "", "has_bridge": true, "options": {"autoplay": true, "buckets": 20, "format": null, "readOnly": false, "weight": 1}, "prop": "", "title": "Total Population", "type": "histogram", "value": "total_pop", "variable_name": "v18db55"}]}, {"credentials": null, "data": "H4sIAOKfXWAC/5XTTWvDMAwG4P/ic2asD0t2r4Wddx89lNYbgS4pWTooJf99TppDetRVyHnQK+Xhxvu1uJ17L8fxNpR9f7mU09j2nWvc17P263afD9eea1eo1dcHtXAd+msZxnZufLih/JXuVjuAEAIHr4pT475L/1PG4T63rF/46NturO9PfT+c2+44LtKbks9RWZr6VhQCHqapWX2w+CgppOAZktkXQJz9qJpl46PJ5wREXnI2+ylrWuaHzLzxyeJDihqwZig2n31AjQtP+BI/m3hOjFrjBzMfQl7Gj7ne0MaPNp+DiBeJ5vgzCizzp8R544vFD/X8E9UszetPGuCZfySIG18Nfsa6ffVEaF8/EdB6fqgbPxl8laiZPAvYr5/j8vdJfpk+W3TOCOIJkp3npLheP87+YfoHPW7k4CYFAAA=", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "vabf72c", "title": "Annual Revenue ($)"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "width", "title": "Annual Revenue ($)", "type": "size-continuous", "variable": "size_value"}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAOKfXWAC/5XTTWvDMAwG4P/ic2asD0t2r4Wddx89lNYbgS4pWTooJf99TppDetRVyHnQK+Xhxvu1uJ17L8fxNpR9f7mU09j2nWvc17P263afD9eea1eo1dcHtXAd+msZxnZufLih/JXuVjuAEAIHr4pT475L/1PG4T63rF/46NturO9PfT+c2+44LtKbks9RWZr6VhQCHqapWX2w+CgppOAZktkXQJz9qJpl46PJ5wREXnI2+ylrWuaHzLzxyeJDihqwZig2n31AjQtP+BI/m3hOjFrjBzMfQl7Gj7ne0MaPNp+DiBeJ5vgzCizzp8R544vFD/X8E9UszetPGuCZfySIG18Nfsa6ffVEaF8/EdB6fqgbPxl8laiZPAvYr5/j8vdJfpk+W3TOCOIJkp3npLheP87+YfoHPW7k4CYFAAA=", "title": "Annual Revenue ($)", "type": "GeoJSON", "viz": "@vabf72c: prop(\\u0027revenue\\u0027)\\n@size_value: ramp(linear(prop(\\u0027revenue\\u0027), globalMIN(prop(\\u0027revenue\\u0027)), globalMAX(prop(\\u0027revenue\\u0027))), [10, 40])\\ncolor: opacity(#FFB927, 0.8)\\nfilter: 1\\nstrokeColor: white\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(sqrt(prop(\\u0027revenue\\u0027)), sqrt(globalMIN(prop(\\u0027revenue\\u0027))), sqrt(globalMAX(prop(\\u0027revenue\\u0027)))), [10, 40])\\n", "widgets": [{"description": "", "footer": "", "has_bridge": true, "options": {"autoplay": true, "buckets": 20, "format": null, "readOnly": false, "weight": 1}, "prop": "", "title": "Annual Revenue ($)", "type": "histogram", "value": "revenue", "variable_name": "vabf72c"}]}];\n", " const mapboxtoken = '';\n", " const show_info = 'None' === 'true';\n", "\n", @@ -7651,10 +7651,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 13, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -7698,7 +7698,7 @@ " 'privacy': 'public'}" ] }, - "execution_count": 14, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -7723,7 +7723,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "Success! Data uploaded to table \"starbucks_stores\" correctly\n", + "Success! Data uploaded to table \"starbucks_stores\" correctly\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "Success! Data uploaded to table \"starbucks_isochrones\" correctly\n" ] }, @@ -7733,7 +7739,7 @@ "'starbucks_isochrones'" ] }, - "execution_count": 15, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -7771,7 +7777,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.8.5" } }, "nbformat": 4, diff --git a/docs/guides/04-Data-Management.ipynb b/docs/guides/04-Data-Management.ipynb index 51d8fdc71..f3b53db85 100644 --- a/docs/guides/04-Data-Management.ipynb +++ b/docs/guides/04-Data-Management.ipynb @@ -263,7 +263,7 @@ "4 POINT (-74.00098 40.59321) " ] }, - "execution_count": 2, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -524,7 +524,7 @@ "[5 rows x 37 columns]" ] }, - "execution_count": 3, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -665,7 +665,7 @@ "4 1148427.411 E POINT (-74.00098 40.59321) " ] }, - "execution_count": 4, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -808,7 +808,7 @@ "4 1148427.411 " ] }, - "execution_count": 6, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -923,7 +923,7 @@ "2 1248133.699 " ] }, - "execution_count": 8, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -973,7 +973,7 @@ "'starbucks_brooklyn_filtered'" ] }, - "execution_count": 10, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -1001,7 +1001,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.8.5" } }, "nbformat": 4, diff --git a/docs/guides/05-Data-Visualization.ipynb b/docs/guides/05-Data-Visualization.ipynb index 0cfbe51ba..1b743dda9 100644 --- a/docs/guides/05-Data-Visualization.ipynb +++ b/docs/guides/05-Data-Visualization.ipynb @@ -1256,7 +1256,7 @@ " const has_legends = 'False' === 'true';\n", " const is_static = 'None' === 'true';\n", " const layer_selector = 'False' === 'true';\n", - " const layers = [{"credentials": null, "data": "H4sIAKMVyl8C/7XSPW8DIQwG4P/CfD1h82GcNVLn7lWGKKEVUnqcKB2i0/33clwqkZ2OWIZHNu8i8n324iBe/Tn/JH+Mt5u/5BAnMYiPvfYtDu+LCNfSJUv1+UIpzCnOPuWwNS7rID59/PI53cvpr/kthimX1kuM6Rqmc66PvpAa2bCEQcvREkg+revwoKA/ZQFxowwR24bC/pRjsnUqYMCGUp0pPUokrSulwLSU7k9Jya4ukBVCQ5n+C2S0eyyc020sbHfKkQRTKVM22FDUf4FKgXrEAqmh3D8kUJsadstPQ3F/STu9f5VCuQ11Wn8BOR2ZplYEAAA=", "encode_data": true, "has_legend_list": true, "interactivity": [], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAKMVyl8C/7XSPW8DIQwG4P/CfD1h82GcNVLn7lWGKKEVUnqcKB2i0/33clwqkZ2OWIZHNu8i8n324iBe/Tn/JH+Mt5u/5BAnMYiPvfYtDu+LCNfSJUv1+UIpzCnOPuWwNS7rID59/PI53cvpr/kthimX1kuM6Rqmc66PvpAa2bCEQcvREkg+revwoKA/ZQFxowwR24bC/pRjsnUqYMCGUp0pPUokrSulwLSU7k9Jya4ukBVCQ5n+C2S0eyyc020sbHfKkQRTKVM22FDUf4FKgXrEAqmh3D8kUJsadstPQ3F/STu9f5VCuQ11Wn8BOR2ZplYEAAA=", "title": null, "type": "GeoJSON", "viz": "color: hex(\\"#EE4D5A\\")\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(zoom(),0,18),[2,10])\\n", "widgets": []}];\n", + " const layers = [{"credentials": null, "data": "H4sIAPifXWAC/7XSPW8DIQwG4P/CfD1h82GcNVLn7lWGKKEVUnqcKB2i0/33clwqkZ2OWIZHNu8i8n324iBe/Tn/JH+Mt5u/5BAnMYiPvfYtDu+LCNfSJUv1+UIpzCnOPuWwNS7rID59/PI53cvpr/kthimX1kuM6Rqmc66PvpAa2bCEQcvREkg+revwoKA/ZQFxowwR24bC/pRjsnUqYMCGUp0pPUokrSulwLSU7k9Jya4ukBVCQ5n+C2S0eyyc020sbHfKkQRTKVM22FDUf4FKgXrEAqmh3D8kUJsadstPQ3F/STu9f5VCuQ11Wn8BOR2ZplYEAAA=", "encode_data": true, "has_legend_list": true, "interactivity": [], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAPifXWAC/7XSPW8DIQwG4P/CfD1h82GcNVLn7lWGKKEVUnqcKB2i0/33clwqkZ2OWIZHNu8i8n324iBe/Tn/JH+Mt5u/5BAnMYiPvfYtDu+LCNfSJUv1+UIpzCnOPuWwNS7rID59/PI53cvpr/kthimX1kuM6Rqmc66PvpAa2bCEQcvREkg+revwoKA/ZQFxowwR24bC/pRjsnUqYMCGUp0pPUokrSulwLSU7k9Jya4ukBVCQ5n+C2S0eyyc020sbHfKkQRTKVM22FDUf4FKgXrEAqmh3D8kUJsadstPQ3F/STu9f5VCuQ11Wn8BOR2ZplYEAAA=", "title": null, "type": "GeoJSON", "viz": "color: hex(\\"#EE4D5A\\")\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(zoom(),0,18),[2,10])\\n", "widgets": []}];\n", " const mapboxtoken = '';\n", " const show_info = 'None' === 'true';\n", "\n", @@ -1280,10 +1280,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 2, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -2536,7 +2536,7 @@ " const has_legends = 'False' === 'true';\n", " const is_static = 'None' === 'true';\n", " const layer_selector = 'False' === 'true';\n", - " const layers = [{"credentials": null, "data": "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", "encode_data": true, "has_legend_list": true, "interactivity": [], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "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", "title": null, "type": "GeoJSON", "viz": "color: hex(\\"#826DBA\\")\\nstrokeColor: opacity(#2c2c2c,ramp(linear(zoom(),2,18),[0.2,0.6]))\\nstrokeWidth: ramp(linear(zoom(),2,18),[0.5,1])\\n", "widgets": []}, {"credentials": null, "data": "H4sIAKQVyl8C/7XSPW8DIQwG4P/CfD1h82GcNVLn7lWGKKEVUnqcKB2i0/33clwqkZ2OWIZHNu8i8n324iBe/Tn/JH+Mt5u/5BAnMYiPvfYtDu+LCNfSJUv1+UIpzCnOPuWwNS7rID59/PI53cvpr/kthimX1kuM6Rqmc66PvpAa2bCEQcvREkg+revwoKA/ZQFxowwR24bC/pRjsnUqYMCGUp0pPUokrSulwLSU7k9Jya4ukBVCQ5n+C2S0eyyc020sbHfKkQRTKVM22FDUf4FKgXrEAqmh3D8kUJsadstPQ3F/STu9f5VCuQ11Wn8BOR2ZplYEAAA=", "encode_data": true, "has_legend_list": true, "interactivity": [], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAKQVyl8C/7XSPW8DIQwG4P/CfD1h82GcNVLn7lWGKKEVUnqcKB2i0/33clwqkZ2OWIZHNu8i8n324iBe/Tn/JH+Mt5u/5BAnMYiPvfYtDu+LCNfSJUv1+UIpzCnOPuWwNS7rID59/PI53cvpr/kthimX1kuM6Rqmc66PvpAa2bCEQcvREkg+revwoKA/ZQFxowwR24bC/pRjsnUqYMCGUp0pPUokrSulwLSU7k9Jya4ukBVCQ5n+C2S0eyyc020sbHfKkQRTKVM22FDUf4FKgXrEAqmh3D8kUJsadstPQ3F/STu9f5VCuQ11Wn8BOR2ZplYEAAA=", "title": null, "type": "GeoJSON", "viz": "color: hex(\\"#EE4D5A\\")\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(zoom(),0,18),[2,10])\\n", "widgets": []}];\n", + " const layers = [{"credentials": null, "data": "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", "encode_data": true, "has_legend_list": true, "interactivity": [], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "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", "title": null, "type": "GeoJSON", "viz": "color: hex(\\"#826DBA\\")\\nstrokeColor: opacity(#2c2c2c,ramp(linear(zoom(),2,18),[0.2,0.6]))\\nstrokeWidth: ramp(linear(zoom(),2,18),[0.5,1])\\n", "widgets": []}, {"credentials": null, "data": "H4sIAPmfXWAC/7XSPW8DIQwG4P/CfD1h82GcNVLn7lWGKKEVUnqcKB2i0/33clwqkZ2OWIZHNu8i8n324iBe/Tn/JH+Mt5u/5BAnMYiPvfYtDu+LCNfSJUv1+UIpzCnOPuWwNS7rID59/PI53cvpr/kthimX1kuM6Rqmc66PvpAa2bCEQcvREkg+revwoKA/ZQFxowwR24bC/pRjsnUqYMCGUp0pPUokrSulwLSU7k9Jya4ukBVCQ5n+C2S0eyyc020sbHfKkQRTKVM22FDUf4FKgXrEAqmh3D8kUJsadstPQ3F/STu9f5VCuQ11Wn8BOR2ZplYEAAA=", "encode_data": true, "has_legend_list": true, "interactivity": [], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAPmfXWAC/7XSPW8DIQwG4P/CfD1h82GcNVLn7lWGKKEVUnqcKB2i0/33clwqkZ2OWIZHNu8i8n324iBe/Tn/JH+Mt5u/5BAnMYiPvfYtDu+LCNfSJUv1+UIpzCnOPuWwNS7rID59/PI53cvpr/kthimX1kuM6Rqmc66PvpAa2bCEQcvREkg+revwoKA/ZQFxowwR24bC/pRjsnUqYMCGUp0pPUokrSulwLSU7k9Jya4ukBVCQ5n+C2S0eyyc020sbHfKkQRTKVM22FDUf4FKgXrEAqmh3D8kUJsadstPQ3F/STu9f5VCuQ11Wn8BOR2ZplYEAAA=", "title": null, "type": "GeoJSON", "viz": "color: hex(\\"#EE4D5A\\")\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(zoom(),0,18),[2,10])\\n", "widgets": []}];\n", " const mapboxtoken = '';\n", " const show_info = 'None' === 'true';\n", "\n", @@ -2560,10 +2560,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 4, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -3846,10 +3846,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 6, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -5118,10 +5118,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 7, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -6402,7 +6402,7 @@ " const has_legends = 'true' === 'true';\n", " const is_static = 'None' === 'true';\n", " const layer_selector = 'False' === 'true';\n", - " const layers = [{"credentials": null, "data": "H4sIAKgVyl8C/5XTwWrDMAwG4HfxOTOSbEvWroOddx89lNYbgS4pWTooJe8+J+3BPeoq5HxI+nNz8/Vc3Kt7L/v5MpW38XQqh7kfB9e5r3vt171+3lx/rF1Qq88PauE8jecyzf3aeHNT+SvDpXZgIIQIXoSWzn2X8afM03VteXzhY+yHub4/jON07If9vEkvErwmBezqWxYE3S1L9/DR4hNnyOAjZrPPSLT6SUS58cnkx4wheFY1+1mFt/lRkRo/WHzMSYDqDtnmRw8kMW5+wNT60eTHHEnq/tHsA2je9q81RI2fbH4EZs+czPtX4nv+co5t/tjiQ81/DnWZ5vtnAUybn+oBGl8MvlI9v/gQyH7/EDA88kfS+NngCyfR4COjPf4xbb8f69P0atGjErIPmO18ze39+oFgnX63/AOe9pnjJwUAAA==", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "vabf72c", "title": "revenue"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "width", "title": "revenue", "type": "size-continuous", "variable": "size_value"}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAKgVyl8C/5XTwWrDMAwG4HfxOTOSbEvWroOddx89lNYbgS4pWTooJe8+J+3BPeoq5HxI+nNz8/Vc3Kt7L/v5MpW38XQqh7kfB9e5r3vt171+3lx/rF1Qq88PauE8jecyzf3aeHNT+SvDpXZgIIQIXoSWzn2X8afM03VteXzhY+yHub4/jON07If9vEkvErwmBezqWxYE3S1L9/DR4hNnyOAjZrPPSLT6SUS58cnkx4wheFY1+1mFt/lRkRo/WHzMSYDqDtnmRw8kMW5+wNT60eTHHEnq/tHsA2je9q81RI2fbH4EZs+czPtX4nv+co5t/tjiQ81/DnWZ5vtnAUybn+oBGl8MvlI9v/gQyH7/EDA88kfS+NngCyfR4COjPf4xbb8f69P0atGjErIPmO18ze39+oFgnX63/AOe9pnjJwUAAA==", "title": null, "type": "GeoJSON", "viz": "@vabf72c: prop(\\u0027revenue\\u0027)\\n@size_value: ramp(linear(prop(\\u0027revenue\\u0027), globalMIN(prop(\\u0027revenue\\u0027)), globalMAX(prop(\\u0027revenue\\u0027))), [2, 40])\\ncolor: opacity(#FFB927, 0.8)\\nfilter: 1\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(sqrt(prop(\\u0027revenue\\u0027)), sqrt(globalMIN(prop(\\u0027revenue\\u0027))), sqrt(globalMAX(prop(\\u0027revenue\\u0027)))), [2, 40])\\n", "widgets": []}];\n", + " const layers = [{"credentials": null, "data": "H4sIAPyfXWAC/5XTwWrDMAwG4HfxOTOSbEvWroOddx89lNYbgS4pWTooJe8+J+3BPeoq5HxI+nNz8/Vc3Kt7L/v5MpW38XQqh7kfB9e5r3vt171+3lx/rF1Qq88PauE8jecyzf3aeHNT+SvDpXZgIIQIXoSWzn2X8afM03VteXzhY+yHub4/jON07If9vEkvErwmBezqWxYE3S1L9/DR4hNnyOAjZrPPSLT6SUS58cnkx4wheFY1+1mFt/lRkRo/WHzMSYDqDtnmRw8kMW5+wNT60eTHHEnq/tHsA2je9q81RI2fbH4EZs+czPtX4nv+co5t/tjiQ81/DnWZ5vtnAUybn+oBGl8MvlI9v/gQyH7/EDA88kfS+NngCyfR4COjPf4xbb8f69P0atGjErIPmO18ze39+oFgnX63/AOe9pnjJwUAAA==", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "vabf72c", "title": "revenue"}, "event": "hover"}], "legends": [{"ascending": false, "description": "", "dynamic": true, "footer": "", "format": null, "prop": "width", "title": "revenue", "type": "size-continuous", "variable": "size_value"}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAPyfXWAC/5XTwWrDMAwG4HfxOTOSbEvWroOddx89lNYbgS4pWTooJe8+J+3BPeoq5HxI+nNz8/Vc3Kt7L/v5MpW38XQqh7kfB9e5r3vt171+3lx/rF1Qq88PauE8jecyzf3aeHNT+SvDpXZgIIQIXoSWzn2X8afM03VteXzhY+yHub4/jON07If9vEkvErwmBezqWxYE3S1L9/DR4hNnyOAjZrPPSLT6SUS58cnkx4wheFY1+1mFt/lRkRo/WHzMSYDqDtnmRw8kMW5+wNT60eTHHEnq/tHsA2je9q81RI2fbH4EZs+czPtX4nv+co5t/tjiQ81/DnWZ5vtnAUybn+oBGl8MvlI9v/gQyH7/EDA88kfS+NngCyfR4COjPf4xbb8f69P0atGjErIPmO18ze39+oFgnX63/AOe9pnjJwUAAA==", "title": null, "type": "GeoJSON", "viz": "@vabf72c: prop(\\u0027revenue\\u0027)\\n@size_value: ramp(linear(prop(\\u0027revenue\\u0027), globalMIN(prop(\\u0027revenue\\u0027)), globalMAX(prop(\\u0027revenue\\u0027))), [2, 40])\\ncolor: opacity(#FFB927, 0.8)\\nfilter: 1\\nstrokeColor: opacity(#222,ramp(linear(zoom(),0,18),[0,0.6]))\\nstrokeWidth: ramp(linear(zoom(),0,18),[0,1])\\nwidth: ramp(linear(sqrt(prop(\\u0027revenue\\u0027)), sqrt(globalMIN(prop(\\u0027revenue\\u0027))), sqrt(globalMAX(prop(\\u0027revenue\\u0027)))), [2, 40])\\n", "widgets": []}];\n", " const mapboxtoken = '';\n", " const show_info = 'None' === 'true';\n", "\n", @@ -6426,10 +6426,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 8, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -7745,10 +7745,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 9, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -9034,7 +9034,7 @@ " const has_legends = 'true' === 'true';\n", " const is_static = 'None' === 'true';\n", " const layer_selector = 'False' === 'true';\n", - " const layers = [{"credentials": null, "data": "H4sIAKkVyl8C/5XTwWrDMAwG4HfxOTOSbEvWroOddx89lNYbgS4pWTooJe8+J+3BPeoq5HxI+nNz8/Vc3Kt7L/v5MpW38XQqh7kfB9e5r3vt171+3lx/rF1Qq88PauE8jecyzf3aeHNT+SvDpXZgIIQIXoSWzn2X8afM03VteXzhY+yHub4/jON07If9vEkvErwmBezqWxYE3S1L9/DR4hNnyOAjZrPPSLT6SUS58cnkx4wheFY1+1mFt/lRkRo/WHzMSYDqDtnmRw8kMW5+wNT60eTHHEnq/tHsA2je9q81RI2fbH4EZs+czPtX4nv+co5t/tjiQ81/DnWZ5vtnAUybn+oBGl8MvlI9v/gQyH7/EDA88kfS+NngCyfR4COjPf4xbb8f69P0atGjErIPmO18ze39+oFgnX63/AOe9pnjJwUAAA==", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "vabf72c", "title": "revenue"}, "event": "hover"}], "legends": [{"ascending": false, "description": "Revenue in dollars ($)", "dynamic": true, "footer": "Source: \\u003ca href=\\"https://www.starbucks.com/\\"\\u003eStarbucks\\u003c/a\\u003e", "format": null, "prop": "width", "title": "Annual Revenue", "type": "size-continuous", "variable": "size_value"}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAKkVyl8C/5XTwWrDMAwG4HfxOTOSbEvWroOddx89lNYbgS4pWTooJe8+J+3BPeoq5HxI+nNz8/Vc3Kt7L/v5MpW38XQqh7kfB9e5r3vt171+3lx/rF1Qq88PauE8jecyzf3aeHNT+SvDpXZgIIQIXoSWzn2X8afM03VteXzhY+yHub4/jON07If9vEkvErwmBezqWxYE3S1L9/DR4hNnyOAjZrPPSLT6SUS58cnkx4wheFY1+1mFt/lRkRo/WHzMSYDqDtnmRw8kMW5+wNT60eTHHEnq/tHsA2je9q81RI2fbH4EZs+czPtX4nv+co5t/tjiQ81/DnWZ5vtnAUybn+oBGl8MvlI9v/gQyH7/EDA88kfS+NngCyfR4COjPf4xbb8f69P0atGjErIPmO18ze39+oFgnX63/AOe9pnjJwUAAA==", "title": null, "type": "GeoJSON", "viz": "@vabf72c: prop(\\u0027revenue\\u0027)\\n@size_value: ramp(linear(prop(\\u0027revenue\\u0027), globalMIN(prop(\\u0027revenue\\u0027)), globalMAX(prop(\\u0027revenue\\u0027))), [10, 50])\\ncolor: opacity(#FFB927, 0)\\nfilter: 1\\nstrokeColor: turquoise\\nstrokeWidth: 2\\nwidth: ramp(linear(sqrt(prop(\\u0027revenue\\u0027)), sqrt(globalMIN(prop(\\u0027revenue\\u0027))), sqrt(globalMAX(prop(\\u0027revenue\\u0027)))), [10, 50])\\n", "widgets": []}];\n", + " const layers = [{"credentials": null, "data": "H4sIAP6fXWAC/5XTwWrDMAwG4HfxOTOSbEvWroOddx89lNYbgS4pWTooJe8+J+3BPeoq5HxI+nNz8/Vc3Kt7L/v5MpW38XQqh7kfB9e5r3vt171+3lx/rF1Qq88PauE8jecyzf3aeHNT+SvDpXZgIIQIXoSWzn2X8afM03VteXzhY+yHub4/jON07If9vEkvErwmBezqWxYE3S1L9/DR4hNnyOAjZrPPSLT6SUS58cnkx4wheFY1+1mFt/lRkRo/WHzMSYDqDtnmRw8kMW5+wNT60eTHHEnq/tHsA2je9q81RI2fbH4EZs+czPtX4nv+co5t/tjiQ81/DnWZ5vtnAUybn+oBGl8MvlI9v/gQyH7/EDA88kfS+NngCyfR4COjPf4xbb8f69P0atGjErIPmO18ze39+oFgnX63/AOe9pnjJwUAAA==", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "vabf72c", "title": "revenue"}, "event": "hover"}], "legends": [{"ascending": false, "description": "Revenue in dollars ($)", "dynamic": true, "footer": "Source: \\u003ca href=\\"https://www.starbucks.com/\\"\\u003eStarbucks\\u003c/a\\u003e", "format": null, "prop": "width", "title": "Annual Revenue", "type": "size-continuous", "variable": "size_value"}], "map_index": 0, "options": {"dateColumns": []}, "source": "H4sIAP6fXWAC/5XTwWrDMAwG4HfxOTOSbEvWroOddx89lNYbgS4pWTooJe8+J+3BPeoq5HxI+nNz8/Vc3Kt7L/v5MpW38XQqh7kfB9e5r3vt171+3lx/rF1Qq88PauE8jecyzf3aeHNT+SvDpXZgIIQIXoSWzn2X8afM03VteXzhY+yHub4/jON07If9vEkvErwmBezqWxYE3S1L9/DR4hNnyOAjZrPPSLT6SUS58cnkx4wheFY1+1mFt/lRkRo/WHzMSYDqDtnmRw8kMW5+wNT60eTHHEnq/tHsA2je9q81RI2fbH4EZs+czPtX4nv+co5t/tjiQ81/DnWZ5vtnAUybn+oBGl8MvlI9v/gQyH7/EDA88kfS+NngCyfR4COjPf4xbb8f69P0atGjErIPmO18ze39+oFgnX63/AOe9pnjJwUAAA==", "title": null, "type": "GeoJSON", "viz": "@vabf72c: prop(\\u0027revenue\\u0027)\\n@size_value: ramp(linear(prop(\\u0027revenue\\u0027), globalMIN(prop(\\u0027revenue\\u0027)), globalMAX(prop(\\u0027revenue\\u0027))), [10, 50])\\ncolor: opacity(#FFB927, 0)\\nfilter: 1\\nstrokeColor: turquoise\\nstrokeWidth: 2\\nwidth: ramp(linear(sqrt(prop(\\u0027revenue\\u0027)), sqrt(globalMIN(prop(\\u0027revenue\\u0027))), sqrt(globalMAX(prop(\\u0027revenue\\u0027)))), [10, 50])\\n", "widgets": []}];\n", " const mapboxtoken = '';\n", " const show_info = 'None' === 'true';\n", "\n", @@ -9058,10 +9058,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 10, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -10406,7 +10406,7 @@ " const has_legends = 'False' === 'true';\n", " const is_static = 'None' === 'true';\n", " const layer_selector = 'False' === 'true';\n", - " const layers = [{"credentials": null, "data": "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", "encode_data": true, "has_legend_list": true, "interactivity": [], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "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", "title": null, "type": "GeoJSON", "viz": "@v464b95: prop(\\u0027educybach\\u0027)\\n@v794f1f: globalSum(prop(\\u0027inccymedhh\\u0027))\\n@vb11b3e: viewportSum(prop(\\u0027popcy\\u0027))\\n@vd11807: prop(\\u0027id_store\\u0027)\\ncolor: hex(\\"#826DBA\\")\\nstrokeColor: opacity(#2c2c2c,ramp(linear(zoom(),2,18),[0.2,0.6]))\\nstrokeWidth: ramp(linear(zoom(),2,18),[0.5,1])\\n", "widgets": [{"description": "", "footer": "", "has_bridge": false, "options": {"autoplay": true, "buckets": 20, "format": null, "readOnly": false, "weight": 1}, "prop": "", "title": "Population", "type": "formula", "value": "viewportSum(prop(\\u0027popcy\\u0027))", "variable_name": "vb11b3e"}, {"description": "", "footer": "", "has_bridge": false, "options": {"autoplay": true, "buckets": 20, "format": null, "readOnly": false, "weight": 1}, "prop": "", "title": "Median Income Average", "type": "formula", "value": "globalSum(prop(\\u0027inccymedhh\\u0027))", "variable_name": "v794f1f"}, {"description": "", "footer": "", "has_bridge": true, "options": {"autoplay": true, "buckets": 20, "format": null, "readOnly": false, "weight": 1}, "prop": "", "title": "Education", "type": "histogram", "value": "educybach", "variable_name": "v464b95"}, {"description": "", "footer": "", "has_bridge": true, "options": {"autoplay": true, "buckets": 20, "format": null, "readOnly": false, "weight": 1}, "prop": "", "title": "Store ID", "type": "category", "value": "id_store", "variable_name": "vd11807"}]}];\n", + " const layers = [{"credentials": null, "data": "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", "encode_data": true, "has_legend_list": true, "interactivity": [], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "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", "title": null, "type": "GeoJSON", "viz": "@v464b95: prop(\\u0027educybach\\u0027)\\n@v794f1f: globalSum(prop(\\u0027inccymedhh\\u0027))\\n@vb11b3e: viewportSum(prop(\\u0027popcy\\u0027))\\n@vd11807: prop(\\u0027id_store\\u0027)\\ncolor: hex(\\"#826DBA\\")\\nstrokeColor: opacity(#2c2c2c,ramp(linear(zoom(),2,18),[0.2,0.6]))\\nstrokeWidth: ramp(linear(zoom(),2,18),[0.5,1])\\n", "widgets": [{"description": "", "footer": "", "has_bridge": false, "options": {"autoplay": true, "buckets": 20, "format": null, "readOnly": false, "weight": 1}, "prop": "", "title": "Population", "type": "formula", "value": "viewportSum(prop(\\u0027popcy\\u0027))", "variable_name": "vb11b3e"}, {"description": "", "footer": "", "has_bridge": false, "options": {"autoplay": true, "buckets": 20, "format": null, "readOnly": false, "weight": 1}, "prop": "", "title": "Median Income Average", "type": "formula", "value": "globalSum(prop(\\u0027inccymedhh\\u0027))", "variable_name": "v794f1f"}, {"description": "", "footer": "", "has_bridge": true, "options": {"autoplay": true, "buckets": 20, "format": null, "readOnly": false, "weight": 1}, "prop": "", "title": "Education", "type": "histogram", "value": "educybach", "variable_name": "v464b95"}, {"description": "", "footer": "", "has_bridge": true, "options": {"autoplay": true, "buckets": 20, "format": null, "readOnly": false, "weight": 1}, "prop": "", "title": "Store ID", "type": "category", "value": "id_store", "variable_name": "vd11807"}]}];\n", " const mapboxtoken = '';\n", " const show_info = 'None' === 'true';\n", "\n", @@ -10430,10 +10430,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 11, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -11685,7 +11685,7 @@ " const has_legends = 'False' === 'true';\n", " const is_static = 'None' === 'true';\n", " const layer_selector = 'False' === 'true';\n", - " const layers = [{"credentials": null, "data": "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", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "v0ab1cc", "title": "Employed Population"}, "event": "click"}, {"attrs": {"format": null, "name": "ve0ae0e", "title": "Median Income"}, "event": "click"}, {"attrs": {"format": null, "name": "vd11807", "title": "Store ID"}, "event": "click"}, {"attrs": {"format": null, "name": "v9b6a6d", "title": "Population"}, "event": "click"}, {"attrs": {"format": null, "name": "v9b6a6d", "title": "Population"}, "event": "hover"}], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "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", "title": null, "type": "GeoJSON", "viz": "@v0ab1cc: prop(\\u0027lbfcyempl\\u0027)\\n@v9b6a6d: prop(\\u0027popcy\\u0027)\\n@vd11807: prop(\\u0027id_store\\u0027)\\n@ve0ae0e: prop(\\u0027inccymedhh\\u0027)\\ncolor: hex(\\"#826DBA\\")\\nstrokeColor: opacity(#2c2c2c,ramp(linear(zoom(),2,18),[0.2,0.6]))\\nstrokeWidth: ramp(linear(zoom(),2,18),[0.5,1])\\n", "widgets": []}];\n", + " const layers = [{"credentials": null, "data": "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", "encode_data": true, "has_legend_list": true, "interactivity": [{"attrs": {"format": null, "name": "v0ab1cc", "title": "Employed Population"}, "event": "click"}, {"attrs": {"format": null, "name": "ve0ae0e", "title": "Median Income"}, "event": "click"}, {"attrs": {"format": null, "name": "vd11807", "title": "Store ID"}, "event": "click"}, {"attrs": {"format": null, "name": "v9b6a6d", "title": "Population"}, "event": "click"}, {"attrs": {"format": null, "name": "v9b6a6d", "title": "Population"}, "event": "hover"}], "legends": [], "map_index": 0, "options": {"dateColumns": []}, "source": "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", "title": null, "type": "GeoJSON", "viz": "@v0ab1cc: prop(\\u0027lbfcyempl\\u0027)\\n@v9b6a6d: prop(\\u0027popcy\\u0027)\\n@vd11807: prop(\\u0027id_store\\u0027)\\n@ve0ae0e: prop(\\u0027inccymedhh\\u0027)\\ncolor: hex(\\"#826DBA\\")\\nstrokeColor: opacity(#2c2c2c,ramp(linear(zoom(),2,18),[0.2,0.6]))\\nstrokeWidth: ramp(linear(zoom(),2,18),[0.5,1])\\n", "widgets": []}];\n", " const mapboxtoken = '';\n", " const show_info = 'None' === 'true';\n", "\n", @@ -11709,10 +11709,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 12, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -13044,7 +13044,7 @@ "}());\n", "\n", "