根据一组坐标的数据给地图着色

2024-04-18 22:26:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一组1000个坐标,每个坐标代表一个州的城市中心。这些镇属于20个县中的一个,我知道哪些镇属于哪个县。我希望根据我所掌握的每个县的数据绘制地图。例如,如果某个县的值为100%,则我希望将该县的颜色设置为深红色;如果某个县与0%关联,则我将将该部分地图颜色设置为白色。在

我没有每个县的边界,因为这些都是老县,要从旧地图上追踪边界需要大量的工作。我有国家的边界,包括岛屿和湖泊等

以下是我掌握的数据:

Town1 50.1,4.89 County1    
Town2 49.9,4.78 County1    
Town3 50.3,4.59 County1    
Town4 50.2,4.99 County1    
Town5 50.0,4.99 County1    
...
Town1000 57.0,8.33 County20 

以及

^{pr2}$

以及州边界。在

解决方案1:所以,创建我想要的地图的一种方法可能是在每个坐标(城镇)周围创建多边形,这个多边形代表地图上最靠近这个城镇的所有区域,而不靠近其他城镇。然后我根据这个多边形所在县的数据给它上色。在

解决方案2:也许更好的方法是在城镇之间混合颜色。所以如果我有两个相邻的城镇在不同的县,一个100%和一个0%,那么他们之间的中间点应该是粉红色的(介于深红色和白色之间)。在

所以我希望能以一个图像文件的形式以编程的方式生成这个地图,这个文件可以很容易地伸缩,我可以把它导入像Photoshop这样的地方,以便添加其他元素。在这种情况下,您会推荐SVG吗?在

在解决方案1中,我可以使用什么库或算法来生成多边形?在

有没有一个库可以用来生成一个SVG文档,它具有解决方案2所要求的类似渐变的网格?在

如果可能的话,我希望使用Python3,但是我对其他语言开放。我也愿意接受SVG的其他解决方案和替代方案。在

我在用MacOS。在


Tags: 数据方法svg颜色地图代表国家解决方案
3条回答

对于python中的Solution1,可以在scipy中使用Voronoi图。以下代码(此SO post的修改版本)创建一个voronoi图,根据每个国家的值使用不同的字母绘制它,并将其保存到图像Map.png

import matplotlib.pyplot as plt
import numpy as np
from scipy.spatial import Voronoi, voronoi_plot_2d
import random

# make up data points
points = np.random.rand(15,2)
values = np.random.uniform(low=0.0, high=1.0, size=(len(points),))

# compute Voronoi tesselation
vor = Voronoi(points)

# plot
voronoi_plot_2d(vor)

# colorize
for region, value in zip(vor.regions, values):
    if not -1 in region:
        polygon = [vor.vertices[i] for i in region]
        plt.fill(*zip(*polygon), color='r',  alpha=value)

plt.savefig('Map.png')

您的积分应该加载到第7行的points变量中,而国家的百分比则加载在第8行的values变量中。在

你的第一个方法叫做Voronoi图

请参见wikipedia中的说明

有一种使用d3libraryforjavascipt来解决这类图表的问题

D3 approach

为了使这个解决方案完整,我在这里粘贴M.Bostock示例中的代码

var w = 1280,
    h = 800;

var projection = d3.geo.azimuthal()
    .mode("equidistant")
    .origin([-98, 38])
    .scale(1400)
    .translate([640, 360]);

var path = d3.geo.path()
    .projection(projection);

var svg = d3.select("body").insert("svg:svg", "h2")
    .attr("width", w)
    .attr("height", h);

var states = svg.append("svg:g")
    .attr("id", "states");

var cells = svg.append("svg:g")
    .attr("id", "cells");

d3.json("us-states.json", function(collection) {
  states.selectAll("path")
      .data(collection.features)
    .enter().append("svg:path")
      .attr("d", path);
});

d3.csv("airports.csv", function(airports) {
  var positions = [];

  airports.forEach(function(airport) {
    positions.push(projection([+airport.longitude, +airport.latitude]));
  });

  // Compute the Voronoi diagram of airports' projected positions.
  var polygons = d3.geom.voronoi(positions);

  var g = cells.selectAll("g")
      .data(airports)
    .enter().append("svg:g");

  g.append("svg:path")
      .attr("class", "cell")
      .attr("d", function(d, i) { return "M" + polygons[i].join("L") + "Z"; })
      .on("mouseover", function(d, i) {
        d3.select("#footer span").text(d.name);
        d3.select("#footer .hint").text(d.city + ", " + d.state);
      });

  g.append("svg:circle")
      .attr("cx", function(d, i) { return positions[i][0]; })
      .attr("cy", function(d, i) { return positions[i][1]; })
      .attr("r", 1.5);
});

使用OpenGL和Gouraud着色可以很容易地实现第二个解决方案,但是将其导出到SVG(或位图之外的任何其他东西)就不容易了。我会考虑任何替代方案。在

虽然通用数据表示有强大的框架,但这项特殊任务的适当工具是GIS。我将尝试解释如何在QGIS中实现这一点。在

  1. 准备导入到QGIS的数据。在

使用以下格式的数据创建CSV文件:

Town,X,Y,County,Value
Town1,50.1,4.89,County1,100
Town2,49.9,4.78,County1,100
Town3,50.3,4.59,County1,100
Town4,50.2,4.99,County1,100
Town5,50.0,4.99,County1,100
...
Town1000,57.0,8.33,County20,0
  1. 将其添加为CSV(分隔文本)层

    • 层->;添加层->;添加分隔文本层
  2. 自定义创建层的样式,以获得您在第二个变体中描述的热图。在

    • 右键单击“层”面板(左下角)上的层标题-“属性”->“符号”
    • 将“单个符号”下拉列表更改为“热图”
    • 点击“应用”
    • 选择“值”字段(是否在CSV中记住它?)在“体重分数”
    • “应用”
    • 根据需要调整其他参数(颜色渐变、半径)
  3. 从这个层创建一个Voronoi多边形

    • 向量->几何工具->Voronoi多边形
    • 点击目标层路径输入框附近的“…”,选择“保存到文件”,保存到GeoJSON层(QGIS不支持CSV中的多边形层,如果理解可以选择其他格式)。在
    • 单击“在后台运行”。在
  4. 自定义新创建图层的样式,使每个县的区域用不同的颜色着色。在

    • 右键单击“层”面板(左下角)上的层标题-“属性”->“符号”
    • 选择“分类”而不是“单一符号”
    • 在“列”下拉列表中选择“县”
    • 单击“分类”将颜色分配给所有县
    • “应用”
  5. 要从当前地图创建SVG,请执行以下操作:

    • 项目->新建打印布局

    • 单击工具面板上的“添加新地图到布局”按钮,绘制地图的大矩形以将其放置在布局上。

    • 单击“导出为SVG”

仅此而已。在

Voronoi多边形上黑色到透明的热图-https://svgshare.com/s/5MZ。在

仅热图-https://svgshare.com/s/5ND。在

我用来生成数据的脚本-https://gist.github.com/ei-grad/1355223cd8a3c6ba16deb454ddef50b4。在

相关问题 更多 >