diff --git a/draftlogs/7731_add.md b/draftlogs/7731_add.md new file mode 100644 index 00000000000..ecb42e372fb --- /dev/null +++ b/draftlogs/7731_add.md @@ -0,0 +1 @@ +- Update USA location lookup for `scattergeo` and `choropleth` traces to use both location names and abbreviations [[7731](https://github.com/plotly/plotly.js/pull/7731)] diff --git a/src/lib/geo_location_utils.js b/src/lib/geo_location_utils.js index e15659f8f45..55338602fd8 100644 --- a/src/lib/geo_location_utils.js +++ b/src/lib/geo_location_utils.js @@ -11,22 +11,23 @@ var loggers = require('./loggers'); var isPlainObject = require('./is_plain_object'); var nestedProperty = require('./nested_property'); var polygon = require('./polygon'); +const { usaLocationAbbreviations, usaLocationList } = require('./usa_location_names'); // make list of all country iso3 ids from at runtime var countryIds = Object.keys(countryRegex); var locationmodeToIdFinder = { 'ISO-3': identity, - 'USA-states': identity, + 'USA-states': usaLocationToAbbreviation, 'country names': countryNameToISO3 }; function countryNameToISO3(countryName) { - for(var i = 0; i < countryIds.length; i++) { + for (var i = 0; i < countryIds.length; i++) { var iso3 = countryIds[i]; var regex = new RegExp(countryRegex[iso3]); - if(regex.test(countryName.trim().toLowerCase())) return iso3; + if (regex.test(countryName.trim().toLowerCase())) return iso3; } loggers.log('Unrecognized country name: ' + countryName + '.'); @@ -34,15 +35,26 @@ function countryNameToISO3(countryName) { return false; } -function locationToFeature(locationmode, location, features) { - if(!location || typeof location !== 'string') return false; +function usaLocationToAbbreviation(loc) { + loc = loc.trim(); + const abbreviation = usaLocationAbbreviations.has(loc.toUpperCase()) + ? loc.toUpperCase() + : usaLocationList[loc.toLowerCase()]; + + if (abbreviation) return abbreviation; + + loggers.log('Unrecognized US location: ' + loc + '.'); + + return false; +} - var locationId = locationmodeToIdFinder[locationmode](location); - var filteredFeatures; - var f, i; +function locationToFeature(locationmode, location, features) { + if (!location || typeof location !== 'string') return false; - if(locationId) { - if(locationmode === 'USA-states') { + const locationId = locationmodeToIdFinder[locationmode](location); + if (locationId) { + let filteredFeatures; + if (locationmode === 'USA-states') { // Filter out features out in USA // // This is important as the Natural Earth files @@ -50,25 +62,18 @@ function locationToFeature(locationmode, location, features) { // which have some overlay in their two-letter ids. For example, // 'WA' is used for both Washington state and Western Australia. filteredFeatures = []; - for(i = 0; i < features.length; i++) { - f = features[i]; - if(f.properties && f.properties.gu && f.properties.gu === 'USA') { - filteredFeatures.push(f); - } + for (const f of features) { + if (f?.properties?.gu === 'USA') filteredFeatures.push(f); } } else { filteredFeatures = features; } - for(i = 0; i < filteredFeatures.length; i++) { - f = filteredFeatures[i]; - if(f.id === locationId) return f; + for (const f of filteredFeatures) { + if (f.id === locationId) return f; } - loggers.log([ - 'Location with id', locationId, - 'does not have a matching topojson feature at this resolution.' - ].join(' ')); + loggers.log(`Location with id ${locationId} does not have a matching topojson feature at this resolution.`); } return false; @@ -83,13 +88,13 @@ function feature2polygons(feature) { var appendPolygon, j, k, m; function doesCrossAntiMerdian(pts) { - for(var l = 0; l < pts.length - 1; l++) { - if(pts[l][0] > 0 && pts[l + 1][0] < 0) return l; + for (var l = 0; l < pts.length - 1; l++) { + if (pts[l][0] > 0 && pts[l + 1][0] < 0) return l; } return null; } - if(loc === 'RUS' || loc === 'FJI') { + if (loc === 'RUS' || loc === 'FJI') { // Russia and Fiji have landmasses that cross the antimeridian, // we need to add +360 to their longitude coordinates, so that // polygon 'contains' doesn't get confused when crossing the antimeridian. @@ -97,32 +102,29 @@ function feature2polygons(feature) { // Note that other countries have polygons on either side of the antimeridian // (e.g. some Aleutian island for the USA), but those don't confuse // the 'contains' method; these are skipped here. - appendPolygon = function(_pts) { + appendPolygon = function (_pts) { var pts; - if(doesCrossAntiMerdian(_pts) === null) { + if (doesCrossAntiMerdian(_pts) === null) { pts = _pts; } else { pts = new Array(_pts.length); - for(m = 0; m < _pts.length; m++) { + for (m = 0; m < _pts.length; m++) { // do not mutate calcdata[i][j].geojson !! - pts[m] = [ - _pts[m][0] < 0 ? _pts[m][0] + 360 : _pts[m][0], - _pts[m][1] - ]; + pts[m] = [_pts[m][0] < 0 ? _pts[m][0] + 360 : _pts[m][0], _pts[m][1]]; } } polygons.push(polygon.tester(pts)); }; - } else if(loc === 'ATA') { + } else if (loc === 'ATA') { // Antarctica has a landmass that wraps around every longitudes which // confuses the 'contains' methods. - appendPolygon = function(pts) { + appendPolygon = function (pts) { var crossAntiMeridianIndex = doesCrossAntiMerdian(pts); // polygon that do not cross anti-meridian need no special handling - if(crossAntiMeridianIndex === null) { + if (crossAntiMeridianIndex === null) { return polygons.push(polygon.tester(pts)); } @@ -135,10 +137,10 @@ function feature2polygons(feature) { var stitch = new Array(pts.length + 1); var si = 0; - for(m = 0; m < pts.length; m++) { - if(m > crossAntiMeridianIndex) { + for (m = 0; m < pts.length; m++) { + if (m > crossAntiMeridianIndex) { stitch[si++] = [pts[m][0] + 360, pts[m][1]]; - } else if(m === crossAntiMeridianIndex) { + } else if (m === crossAntiMeridianIndex) { stitch[si++] = pts[m]; stitch[si++] = [pts[m][0], -90]; } else { @@ -155,21 +157,21 @@ function feature2polygons(feature) { }; } else { // otherwise using same array ref is fine - appendPolygon = function(pts) { + appendPolygon = function (pts) { polygons.push(polygon.tester(pts)); }; } - switch(geometry.type) { + switch (geometry.type) { case 'MultiPolygon': - for(j = 0; j < coords.length; j++) { - for(k = 0; k < coords[j].length; k++) { + for (j = 0; j < coords.length; j++) { + for (k = 0; k < coords[j].length; k++) { appendPolygon(coords[j][k]); } } break; case 'Polygon': - for(j = 0; j < coords.length; j++) { + for (j = 0; j < coords.length; j++) { appendPolygon(coords[j]); } break; @@ -185,7 +187,7 @@ function getTraceGeojson(trace) { // This should not happen, but just in case something goes // really wrong when fetching the GeoJSON - if(!isPlainObject(geojsonIn)) { + if (!isPlainObject(geojsonIn)) { loggers.error('Oops ... something went wrong when fetching ' + g); return false; } @@ -197,15 +199,15 @@ function extractTraceFeature(calcTrace) { var trace = calcTrace[0].trace; var geojsonIn = getTraceGeojson(trace); - if(!geojsonIn) return false; + if (!geojsonIn) return false; var lookup = {}; var featuresOut = []; var i; - for(i = 0; i < trace._length; i++) { + for (i = 0; i < trace._length; i++) { var cdi = calcTrace[i]; - if(cdi.loc || cdi.loc === 0) { + if (cdi.loc || cdi.loc === 0) { lookup[cdi.loc] = cdi; } } @@ -214,10 +216,10 @@ function extractTraceFeature(calcTrace) { var id = nestedProperty(fIn, trace.featureidkey || 'id').get(); var cdi = lookup[id]; - if(cdi) { + if (cdi) { var geometry = fIn.geometry; - if(geometry.type === 'Polygon' || geometry.type === 'MultiPolygon') { + if (geometry.type === 'Polygon' || geometry.type === 'MultiPolygon') { var fOut = { type: 'Feature', id: id, @@ -238,11 +240,15 @@ function extractTraceFeature(calcTrace) { featuresOut.push(fOut); } else { - loggers.log([ - 'Location', cdi.loc, 'does not have a valid GeoJSON geometry.', - 'Traces with locationmode *geojson-id* only support', - '*Polygon* and *MultiPolygon* geometries.' - ].join(' ')); + loggers.log( + [ + 'Location', + cdi.loc, + 'does not have a valid GeoJSON geometry.', + 'Traces with locationmode *geojson-id* only support', + '*Polygon* and *MultiPolygon* geometries.' + ].join(' ') + ); } } @@ -251,10 +257,10 @@ function extractTraceFeature(calcTrace) { delete lookup[id]; } - switch(geojsonIn.type) { + switch (geojsonIn.type) { case 'FeatureCollection': var featuresIn = geojsonIn.features; - for(i = 0; i < featuresIn.length; i++) { + for (i = 0; i < featuresIn.length; i++) { appendFeature(featuresIn[i]); } break; @@ -262,20 +268,25 @@ function extractTraceFeature(calcTrace) { appendFeature(geojsonIn); break; default: - loggers.warn([ - 'Invalid GeoJSON type', (geojsonIn.type || 'none') + '.', - 'Traces with locationmode *geojson-id* only support', - '*FeatureCollection* and *Feature* types.' - ].join(' ')); + loggers.warn( + [ + 'Invalid GeoJSON type', + (geojsonIn.type || 'none') + '.', + 'Traces with locationmode *geojson-id* only support', + '*FeatureCollection* and *Feature* types.' + ].join(' ') + ); return false; } - for(var loc in lookup) { - loggers.log([ - 'Location *' + loc + '*', - 'does not have a matching feature with id-key', - '*' + trace.featureidkey + '*.' - ].join(' ')); + for (var loc in lookup) { + loggers.log( + [ + 'Location *' + loc + '*', + 'does not have a matching feature with id-key', + '*' + trace.featureidkey + '*.' + ].join(' ') + ); } return featuresOut; @@ -289,14 +300,14 @@ function findCentroid(feature) { var geometry = feature.geometry; var poly; - if(geometry.type === 'MultiPolygon') { + if (geometry.type === 'MultiPolygon') { var coords = geometry.coordinates; var maxArea = 0; - for(var i = 0; i < coords.length; i++) { - var polyi = {type: 'Polygon', coordinates: coords[i]}; + for (var i = 0; i < coords.length; i++) { + var polyi = { type: 'Polygon', coordinates: coords[i] }; var area = turfArea(polyi); - if(area > maxArea) { + if (area > maxArea) { maxArea = area; poly = polyi; } @@ -313,13 +324,14 @@ function fetchTraceGeoData(calcData) { var promises = []; function fetch(url) { - return new Promise(function(resolve, reject) { - d3.json(url, function(err, d) { - if(err) { + return new Promise(function (resolve, reject) { + d3.json(url, function (err, d) { + if (err) { delete PlotlyGeoAssets[url]; - var msg = err.status === 404 ? - ('GeoJSON at URL "' + url + '" does not exist.') : - ('Unexpected error while fetching from ' + url); + var msg = + err.status === 404 + ? 'GeoJSON at URL "' + url + '" does not exist.' + : 'Unexpected error while fetching from ' + url; return reject(new Error(msg)); } @@ -330,14 +342,14 @@ function fetchTraceGeoData(calcData) { } function wait(url) { - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { var cnt = 0; - var interval = setInterval(function() { - if(PlotlyGeoAssets[url] && PlotlyGeoAssets[url] !== 'pending') { + var interval = setInterval(function () { + if (PlotlyGeoAssets[url] && PlotlyGeoAssets[url] !== 'pending') { clearInterval(interval); return resolve(PlotlyGeoAssets[url]); } - if(cnt > 100) { + if (cnt > 100) { clearInterval(interval); return reject('Unexpected error while fetching from ' + url); } @@ -346,15 +358,15 @@ function fetchTraceGeoData(calcData) { }); } - for(var i = 0; i < calcData.length; i++) { + for (var i = 0; i < calcData.length; i++) { var trace = calcData[i][0].trace; var url = trace.geojson; - if(typeof url === 'string') { - if(!PlotlyGeoAssets[url]) { + if (typeof url === 'string') { + if (!PlotlyGeoAssets[url]) { PlotlyGeoAssets[url] = 'pending'; promises.push(fetch(url)); - } else if(PlotlyGeoAssets[url] === 'pending') { + } else if (PlotlyGeoAssets[url] === 'pending') { promises.push(wait(url)); } } diff --git a/src/lib/usa_location_names.js b/src/lib/usa_location_names.js new file mode 100644 index 00000000000..117451364d4 --- /dev/null +++ b/src/lib/usa_location_names.js @@ -0,0 +1,65 @@ +'use strict'; + +// Mapping of lowercase full US state names to two-letter abbreviations +const usaLocationList = { + alabama: 'AL', + alaska: 'AK', + arizona: 'AZ', + arkansas: 'AR', + california: 'CA', + colorado: 'CO', + connecticut: 'CT', + delaware: 'DE', + 'district of columbia': 'DC', + florida: 'FL', + georgia: 'GA', + hawaii: 'HI', + idaho: 'ID', + illinois: 'IL', + indiana: 'IN', + iowa: 'IA', + kansas: 'KS', + kentucky: 'KY', + louisiana: 'LA', + maine: 'ME', + maryland: 'MD', + massachusetts: 'MA', + michigan: 'MI', + minnesota: 'MN', + mississippi: 'MS', + missouri: 'MO', + montana: 'MT', + nebraska: 'NE', + nevada: 'NV', + 'new hampshire': 'NH', + 'new jersey': 'NJ', + 'new mexico': 'NM', + 'new york': 'NY', + 'north carolina': 'NC', + 'north dakota': 'ND', + ohio: 'OH', + oklahoma: 'OK', + oregon: 'OR', + pennsylvania: 'PA', + 'rhode island': 'RI', + 'south carolina': 'SC', + 'south dakota': 'SD', + tennessee: 'TN', + texas: 'TX', + utah: 'UT', + vermont: 'VT', + virginia: 'VA', + washington: 'WA', + 'washington dc': 'DC', + 'washington d.c.': 'DC', + 'west virginia': 'WV', + wisconsin: 'WI', + wyoming: 'WY' +}; + +const usaLocationAbbreviations = new Set(Object.values(usaLocationList)); + +module.exports = { + usaLocationAbbreviations, + usaLocationList +}; diff --git a/src/traces/scattergeo/attributes.js b/src/traces/scattergeo/attributes.js index f2fb2639cf8..9059261f671 100644 --- a/src/traces/scattergeo/attributes.js +++ b/src/traces/scattergeo/attributes.js @@ -48,7 +48,9 @@ module.exports = overrideAll( 'to regions on the map.', 'Values *ISO-3*, *USA-states*, *country names* correspond to features on', 'the base map and value *geojson-id* corresponds to features from a custom', - 'GeoJSON linked to the `geojson` attribute.' + 'GeoJSON linked to the `geojson` attribute.', + '*USA-states* accepts both two-letter abbreviations (e.g. *CA*) and', + 'full state names (e.g. *California*).' ].join(' ') }, diff --git a/test/image/baselines/geo_choropleth-usa.png b/test/image/baselines/geo_choropleth-usa.png index b4e155406d8..16716b556bf 100644 Binary files a/test/image/baselines/geo_choropleth-usa.png and b/test/image/baselines/geo_choropleth-usa.png differ diff --git a/test/image/baselines/map_custom-style.png b/test/image/baselines/map_custom-style.png index 7a79826bc26..6db20064a00 100644 Binary files a/test/image/baselines/map_custom-style.png and b/test/image/baselines/map_custom-style.png differ diff --git a/test/image/mocks/geo_choropleth-usa.json b/test/image/mocks/geo_choropleth-usa.json index edad7315c0f..88329cbb828 100644 --- a/test/image/mocks/geo_choropleth-usa.json +++ b/test/image/mocks/geo_choropleth-usa.json @@ -2,6 +2,13 @@ "data": [ { "autocolorscale": false, + "colorbar": { + "title": { "text": "Millions USD" } + }, + "locationmode": "USA-states", + "name": "", + "type": "choropleth", + "zmin": 13.31, "zmax": 16472.88, "colorscale": [ [0, "rgb(242,240,247)"], @@ -63,7 +70,6 @@ "Wisconsin
--
Beef: 107.3
Pork: 38.6
Poultry: 34.5
Dairy: 633.6
--
Fruits: 133.8
Veggies: 148.99
--
Wheat: 96.7
Corn: 460.5
Cotton: 0.0", "Wyoming
--
Beef: 75.1
Pork: 33.2
Poultry: 0.1
Dairy: 2.89
--
Fruits: 0.17
Veggies: 10.23
--
Wheat: 20.7
Corn: 9.0
Cotton: 0.0" ], - "zmin": 13.31, "locations": [ "AL", "AK", @@ -116,10 +122,6 @@ "WI", "WY" ], - "colorbar": { - "title": { "text": "Millions USD" } - }, - "type": "choropleth", "z": [ 1390.63, 13.31, 1463.17, 3586.02, 16472.88, 1851.33, 259.62, 282.19, 3764.09, 2860.84, 401.84, 2078.89, 8709.48, 5050.23, 11273.76, 4589.01, @@ -128,8 +130,138 @@ 3761.96, 3979.79, 1646.41, 1794.57, 1969.87, 31.59, 929.93, 3770.19, 1535.13, 6648.22, 453.39, 180.14, 1146.48, 3894.81, 138.89, 3090.23, 349.69 + ] + }, + { + "autocolorscale": false, + "geo": "geo2", + "locationmode": "USA-states", + "name": "", + "showscale": false, + "type": "choropleth", + "zmax": 16472.88, + "zmin": 13.31, + "colorscale": [ + [0, "rgb(242,240,247)"], + [0.2, "rgb(218,218,235)"], + [0.4, "rgb(188,189,220)"], + [0.6, "rgb(158,154,200)"], + [0.8, "rgb(117,107,177)"], + [1, "rgb(84,39,143)"] + ], + "text": [ + "Alabama
--
Beef: 34.4
Pork: 10.6
Poultry: 481.0
Dairy: 4.06
--
Fruits: 25.11
Veggies: 14.33
--
Wheat: 70.0
Corn: 34.9
Cotton: 317.61", + "Alaska
--
Beef: 0.2
Pork: 0.1
Poultry: 0.0
Dairy: 0.19
--
Fruits: 0.0
Veggies: 1.56
--
Wheat: 0.0
Corn: 0.0
Cotton: 0.0", + "Arizona
--
Beef: 71.3
Pork: 17.9
Poultry: 0.0
Dairy: 105.48
--
Fruits: 60.27
Veggies: 386.91
--
Wheat: 48.7
Corn: 7.3
Cotton: 423.95", + "Arkansas
--
Beef: 53.2
Pork: 29.4
Poultry: 562.9
Dairy: 3.53
--
Fruits: 6.88
Veggies: 11.45
--
Wheat: 114.5
Corn: 69.5
Cotton: 665.44", + " California
--
Beef: 228.7
Pork: 11.1
Poultry: 225.4
Dairy: 929.95
--
Fruits: 8736.4
Veggies: 2106.79
--
Wheat: 249.3
Corn: 34.6
Cotton: 1064.95", + "Colorado
--
Beef: 261.4
Pork: 66.0
Poultry: 14.0
Dairy: 71.94
--
Fruits: 17.99
Veggies: 118.27
--
Wheat: 400.5
Corn: 183.2
Cotton: 0.0", + "Connecticut
--
Beef: 1.1
Pork: 0.1
Poultry: 6.9
Dairy: 9.49
--
Fruits: 13.1
Veggies: 11.16
--
Wheat: 0.0
Corn: 0.0
Cotton: 0.0", + "Delaware
--
Beef: 0.4
Pork: 0.6
Poultry: 114.7
Dairy: 2.3
--
Fruits: 1.53
Veggies: 20.03
--
Wheat: 22.9
Corn: 26.9
Cotton: 0.0", + "Florida
--
Beef: 42.6
Pork: 0.9
Poultry: 56.9
Dairy: 66.31
--
Fruits: 1371.36
Veggies: 450.86
--
Wheat: 1.8
Corn: 3.5
Cotton: 78.24", + "Georgia
--
Beef: 31.0
Pork: 18.9
Poultry: 630.4
Dairy: 38.38
--
Fruits: 233.51
Veggies: 154.77
--
Wheat: 65.4
Corn: 57.8
Cotton: 1154.07", + "Hawaii
--
Beef: 4.0
Pork: 0.7
Poultry: 1.3
Dairy: 1.16
--
Fruits: 55.51
Veggies: 24.83
--
Wheat: 0.0
Corn: 0.0
Cotton: 0.0", + "Idaho
--
Beef: 119.8
Pork: 0.0
Poultry: 2.4
Dairy: 294.6
--
Fruits: 21.64
Veggies: 319.19
--
Wheat: 568.2
Corn: 24.0
Cotton: 0.0", + "Illinois
--
Beef: 53.7
Pork: 394.0
Poultry: 14.0
Dairy: 45.82
--
Fruits: 12.53
Veggies: 39.95
--
Wheat: 223.8
Corn: 2228.5
Cotton: 0.0", + "Indiana
--
Beef: 21.9
Pork: 341.9
Poultry: 165.6
Dairy: 89.7
--
Fruits: 12.98
Veggies: 37.89
--
Wheat: 114.0
Corn: 1123.2
Cotton: 0.0", + "Iowa
--
Beef: 289.8
Pork: 1895.6
Poultry: 155.6
Dairy: 107.0
--
Fruits: 3.24
Veggies: 7.1
--
Wheat: 3.1
Corn: 2529.8
Cotton: 0.0", + "Kansas
--
Beef: 659.3
Pork: 179.4
Poultry: 6.4
Dairy: 65.45
--
Fruits: 3.11
Veggies: 9.32
--
Wheat: 1426.5
Corn: 457.3
Cotton: 43.98", + "Kentucky
--
Beef: 54.8
Pork: 34.2
Poultry: 151.3
Dairy: 28.27
--
Fruits: 6.6
Veggies: 0.0
--
Wheat: 149.3
Corn: 179.1
Cotton: 0.0", + "Louisiana
--
Beef: 19.8
Pork: 0.8
Poultry: 77.2
Dairy: 6.02
--
Fruits: 17.83
Veggies: 17.25
--
Wheat: 78.7
Corn: 91.4
Cotton: 280.42", + "Maine
--
Beef: 1.4
Pork: 0.5
Poultry: 10.4
Dairy: 16.18
--
Fruits: 52.01
Veggies: 62.9
--
Wheat: 0.0
Corn: 0.0
Cotton: 0.0", + "Maryland
--
Beef: 5.6
Pork: 3.1
Poultry: 127.0
Dairy: 24.81
--
Fruits: 12.9
Veggies: 20.43
--
Wheat: 55.8
Corn: 54.1
Cotton: 0.0", + "Massachusetts
--
Beef: 0.6
Pork: 0.5
Poultry: 0.6
Dairy: 5.81
--
Fruits: 80.83
Veggies: 21.13
--
Wheat: 0.0
Corn: 0.0
Cotton: 0.0", + "Michigan
--
Beef: 37.7
Pork: 118.1
Poultry: 32.6
Dairy: 214.82
--
Fruits: 257.69
Veggies: 189.96
--
Wheat: 247.0
Corn: 381.5
Cotton: 0.0", + "Minnesota
--
Beef: 112.3
Pork: 740.4
Poultry: 189.2
Dairy: 218.05
--
Fruits: 7.91
Veggies: 120.37
--
Wheat: 538.1
Corn: 1264.3
Cotton: 0.0", + "Mississippi
--
Beef: 12.8
Pork: 30.4
Poultry: 370.8
Dairy: 5.45
--
Fruits: 17.04
Veggies: 27.87
--
Wheat: 102.2
Corn: 110.0
Cotton: 494.75", + "Missouri
--
Beef: 137.2
Pork: 277.3
Poultry: 196.1
Dairy: 34.26
--
Fruits: 13.18
Veggies: 17.9
--
Wheat: 161.7
Corn: 428.8
Cotton: 345.29", + "Montana
--
Beef: 105.0
Pork: 16.7
Poultry: 1.7
Dairy: 6.82
--
Fruits: 3.3
Veggies: 45.27
--
Wheat: 1198.1
Corn: 5.4
Cotton: 0.0", + "Nebraska
--
Beef: 762.2
Pork: 262.5
Poultry: 31.4
Dairy: 30.07
--
Fruits: 2.16
Veggies: 53.5
--
Wheat: 292.3
Corn: 1735.9
Cotton: 0.0", + "Nevada
--
Beef: 21.8
Pork: 0.2
Poultry: 0.0
Dairy: 16.57
--
Fruits: 1.19
Veggies: 27.93
--
Wheat: 5.4
Corn: 0.0
Cotton: 0.0", + "New Hampshire
--
Beef: 0.6
Pork: 0.2
Poultry: 0.8
Dairy: 7.46
--
Fruits: 7.98
Veggies: 4.5
--
Wheat: 0.0
Corn: 0.0
Cotton: 0.0", + "New Jersey
--
Beef: 0.8
Pork: 0.4
Poultry: 4.6
Dairy: 3.37
--
Fruits: 109.45
Veggies: 56.54
--
Wheat: 6.7
Corn: 10.1
Cotton: 0.0", + "New Mexico
--
Beef: 117.2
Pork: 0.1
Poultry: 0.3
Dairy: 191.01
--
Fruits: 101.9
Veggies: 43.88
--
Wheat: 13.9
Corn: 11.2
Cotton: 72.62", + "New York
--
Beef: 22.2
Pork: 5.8
Poultry: 17.7
Dairy: 331.8
--
Fruits: 202.56
Veggies: 143.37
--
Wheat: 29.9
Corn: 106.1
Cotton: 0.0", + "North Carolina
--
Beef: 24.8
Pork: 702.8
Poultry: 598.4
Dairy: 24.9
--
Fruits: 74.47
Veggies: 150.45
--
Wheat: 200.3
Corn: 92.2
Cotton: 470.86", + "North Dakota
--
Beef: 78.5
Pork: 16.1
Poultry: 0.5
Dairy: 8.14
--
Fruits: 0.25
Veggies: 130.79
--
Wheat: 1664.5
Corn: 236.1
Cotton: 0.0", + "Ohio
--
Beef: 36.2
Pork: 199.1
Poultry: 129.9
Dairy: 134.57
--
Fruits: 27.21
Veggies: 53.53
--
Wheat: 207.4
Corn: 535.1
Cotton: 0.0", + "Oklahoma
--
Beef: 337.6
Pork: 265.3
Poultry: 131.1
Dairy: 24.35
--
Fruits: 9.24
Veggies: 8.9
--
Wheat: 324.8
Corn: 27.5
Cotton: 110.54", + "Oregon
--
Beef: 58.8
Pork: 1.4
Poultry: 14.2
Dairy: 63.66
--
Fruits: 315.04
Veggies: 126.5
--
Wheat: 320.3
Corn: 11.7
Cotton: 0.0", + "Pennsylvania
--
Beef: 50.9
Pork: 91.3
Poultry: 169.8
Dairy: 280.87
--
Fruits: 89.48
Veggies: 38.26
--
Wheat: 41.0
Corn: 112.1
Cotton: 0.0", + "Rhode Island
--
Beef: 0.1
Pork: 0.1
Poultry: 0.2
Dairy: 0.52
--
Fruits: 2.83
Veggies: 3.02
--
Wheat: 0.0
Corn: 0.0
Cotton: 0.0", + "South Carolina
--
Beef: 15.2
Pork: 10.9
Poultry: 186.5
Dairy: 7.62
--
Fruits: 53.45
Veggies: 42.66
--
Wheat: 55.3
Corn: 32.1
Cotton: 206.1", + "South Dakota
--
Beef: 193.5
Pork: 160.2
Poultry: 29.3
Dairy: 46.77
--
Fruits: 0.8
Veggies: 4.06
--
Wheat: 704.5
Corn: 643.6
Cotton: 0.0", + "Tennessee
--
Beef: 51.1
Pork: 17.6
Poultry: 82.4
Dairy: 21.18
--
Fruits: 6.23
Veggies: 24.67
--
Wheat: 100.0
Corn: 88.8
Cotton: 363.83", + "Texas
--
Beef: 961.0
Pork: 42.7
Poultry: 339.2
Dairy: 240.55
--
Fruits: 99.9
Veggies: 115.23
--
Wheat: 309.7
Corn: 167.2
Cotton: 2308.76", + "Utah
--
Beef: 27.9
Pork: 59.0
Poultry: 23.1
Dairy: 48.6
--
Fruits: 12.34
Veggies: 6.6
--
Wheat: 42.8
Corn: 5.3
Cotton: 0.0", + "Vermont
--
Beef: 6.2
Pork: 0.2
Poultry: 0.9
Dairy: 65.98
--
Fruits: 8.01
Veggies: 4.05
--
Wheat: 0.0
Corn: 0.0
Cotton: 0.0", + "Virginia
--
Beef: 39.5
Pork: 16.9
Poultry: 164.7
Dairy: 47.85
--
Fruits: 36.48
Veggies: 27.25
--
Wheat: 77.5
Corn: 39.5
Cotton: 64.84", + "Washington
--
Beef: 59.2
Pork: 0.0
Poultry: 35.6
Dairy: 154.18
--
Fruits: 1738.57
Veggies: 363.79
--
Wheat: 786.3
Corn: 29.5
Cotton: 0.0", + "West Virginia
--
Beef: 12.0
Pork: 0.3
Poultry: 45.4
Dairy: 3.9
--
Fruits: 11.54
Veggies: 0.0
--
Wheat: 1.6
Corn: 3.5
Cotton: 0.0", + "Wisconsin
--
Beef: 107.3
Pork: 38.6
Poultry: 34.5
Dairy: 633.6
--
Fruits: 133.8
Veggies: 148.99
--
Wheat: 96.7
Corn: 460.5
Cotton: 0.0", + "Wyoming
--
Beef: 75.1
Pork: 33.2
Poultry: 0.1
Dairy: 2.89
--
Fruits: 0.17
Veggies: 10.23
--
Wheat: 20.7
Corn: 9.0
Cotton: 0.0" + ], + "locations": [ + "Alabama", + "Alaska", + "Arizona", + "Arkansas", + "California", + "Colorado", + "Connecticut", + "Delaware", + "Florida", + "Georgia", + "Hawaii", + "Idaho", + "Illinois", + "Indiana", + "Iowa", + "Kansas", + "Kentucky", + "Louisiana", + "Maine", + "Maryland", + "Massachusetts", + "Michigan", + "Minnesota", + "Mississippi", + "Missouri", + "Montana", + "Nebraska", + "Nevada", + "New Hampshire", + "New Jersey", + "New Mexico", + "New York", + "North Carolina", + "North Dakota", + "Ohio", + "Oklahoma", + "Oregon", + "Pennsylvania", + "Rhode Island", + "South Carolina", + "South Dakota", + "Tennessee", + "Texas", + "Utah", + "Vermont", + "Virginia", + "Washington", + "West Virginia", + "Wisconsin", + "Wyoming" ], - "locationmode": "USA-states" + "z": [ + 1390.63, 13.31, 1463.17, 3586.02, 16472.88, 1851.33, 259.62, 282.19, + 3764.09, 2860.84, 401.84, 2078.89, 8709.48, 5050.23, 11273.76, 4589.01, + 1889.15, 1914.23, 278.37, 692.75, 248.65, 3164.16, 7192.33, 2170.8, + 3933.42, 1718, 7114.13, 139.89, 73.06, 500.4, 751.58, 1488.9, 3806.05, + 3761.96, 3979.79, 1646.41, 1794.57, 1969.87, 31.59, 929.93, 3770.19, + 1535.13, 6648.22, 453.39, 180.14, 1146.48, 3894.81, 138.89, 3090.23, + 349.69 + ] } ], "layout": { @@ -138,7 +270,7 @@ "text": "2011 US Agriculture Exports by State
(Hover for breakdown)" }, "showlegend": false, - "height": 598, + "height": 1200, "width": 870, "geo": { "showlakes": true, @@ -146,7 +278,37 @@ "projection": { "type": "albers usa" }, - "lakecolor": "rgb(255, 255, 255)" - } + "lakecolor": "rgb(255, 255, 255)", + "domain": { "y": [0.55, 1] } + }, + "geo2": { + "showlakes": true, + "scope": "usa", + "projection": { + "type": "albers usa" + }, + "lakecolor": "rgb(255, 255, 255)", + "domain": { "y": [0, 0.45] } + }, + "annotations": [ + { + "text": "Lookup by two letter location abbreviation", + "x": 0.5, + "y": 0.53, + "xref": "paper", + "yref": "paper", + "showarrow": false, + "font": { "size": 16 } + }, + { + "text": "Lookup by full location name", + "x": 0.5, + "y": -0.02, + "xref": "paper", + "yref": "paper", + "showarrow": false, + "font": { "size": 16 } + } + ] } } diff --git a/test/plot-schema.json b/test/plot-schema.json index 9e6c6299dad..565942dec36 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -25447,7 +25447,7 @@ "valType": "number" }, "locationmode": { - "description": "The library used by the *country names* `locationmode` option is changing in an upcoming version. Country names in existing plots may not work in the new version. Determines the set of locations used to match entries in `locations` to regions on the map. Values *ISO-3*, *USA-states*, *country names* correspond to features on the base map and value *geojson-id* corresponds to features from a custom GeoJSON linked to the `geojson` attribute.", + "description": "The library used by the *country names* `locationmode` option is changing in an upcoming version. Country names in existing plots may not work in the new version. Determines the set of locations used to match entries in `locations` to regions on the map. Values *ISO-3*, *USA-states*, *country names* correspond to features on the base map and value *geojson-id* corresponds to features from a custom GeoJSON linked to the `geojson` attribute. *USA-states* accepts both two-letter abbreviations (e.g. *CA*) and full state names (e.g. *California*).", "dflt": "ISO-3", "editType": "calc", "valType": "enumerated", @@ -67366,7 +67366,7 @@ } }, "locationmode": { - "description": "The library used by the *country names* `locationmode` option is changing in an upcoming version. Country names in existing plots may not work in the new version. Determines the set of locations used to match entries in `locations` to regions on the map. Values *ISO-3*, *USA-states*, *country names* correspond to features on the base map and value *geojson-id* corresponds to features from a custom GeoJSON linked to the `geojson` attribute.", + "description": "The library used by the *country names* `locationmode` option is changing in an upcoming version. Country names in existing plots may not work in the new version. Determines the set of locations used to match entries in `locations` to regions on the map. Values *ISO-3*, *USA-states*, *country names* correspond to features on the base map and value *geojson-id* corresponds to features from a custom GeoJSON linked to the `geojson` attribute. *USA-states* accepts both two-letter abbreviations (e.g. *CA*) and full state names (e.g. *California*).", "dflt": "ISO-3", "editType": "calc", "valType": "enumerated",