数据可视化【十三】地区分布图

在前面的博客中已经介绍了如何绘制地图,这一节学习如何绘制地区分布图。如果对绘制地图还不熟悉的话可以了解一下之前我写的博客:数据可视化【十】绘制地图

Intergrating(整合) TopoJSON with tabular data(列表数据)

在前面的博客中没有使用到tsv文件,因为我找到的TopoJSON中本来就包含国家的名字。但是如果想要知道国家更多的数据仅仅知道国家的名字是不够的,因此还需要导入关于国家其他数据的tsv文件。当导入多个文件的时候最好使用Promis.all,这样就可以在文件全部都加载后再开始执行。需要将多个任务都放在一个数组里面,然后再在then中用一个数组接收读入的数据。

Promise.all([tsv('https://unpkg.com/world-atlas@1.1.4/world/50m.tsv'),json('https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-50m.json')
]).then(([tsvData, topsJSONdata]) => {}

为了快速处理tsv文件,我们使用reduce函数将其放到一个类中。其中iso_n3JSON文件中的id对应

const rowById = tsvData.reduce((accumulator, d)=>{accumulator[d.iso_n3] = d;return accumulator;}, {});//前面是reduce的执行,后面是accumulator的初始值

为了使得JSON文件中的每个元素都包含这个国家更多的信息,我们使用assign函数将同一个国家的信息进行合并

const countries = feature(topsJSONdata, topsJSONdata.objects.countries);// console.log(countries);countries.features.forEach(d => {Object.assign(d.properties, rowById[d.id]);});

Creating a loadAndProcessData module

上面载入数据的过程其实可以当作另一个模块,因此我们把上面的代码单独放在一个用于加载数据的文件中
loadAndProcessData.js

import {json, tsv} from 'd3';
import {feature} from 'topojson';export const loadAndProcessData = () => Promise.all([tsv('https://unpkg.com/world-atlas@1.1.4/world/50m.tsv'),json('https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-50m.json')
]).then(([tsvData, topsJSONdata]) => {const rowById = tsvData.reduce((accumulator, d)=>{accumulator[d.iso_n3] = d;return accumulator;}, {});const countries = feature(topsJSONdata, topsJSONdata.objects.countries);// console.log(countries);countries.features.forEach(d => {Object.assign(d.properties, rowById[d.id]);});return countries;});

并在index.js中将相应的代码都放在loadAndProcessData函数的then

Visualizing an ordered attribute with color

在得到国家的其他属性之后,我们就可以根据国家的其他标签给国家上色
我们可以首先观察一下tsv文件中都有什么。太多了这里就不显示了,比如说里面有一个标签是经济,我们不妨使用经济给不同国家不同的颜色。

为了方便修改标签,我们把获取数据属性的操作放到一个函数里,并且在后面所有的地方都通过这个函数获取属性,这样做的好处是如果我们不想要这个标签,我们只需要在这一个地方进行修改就可以。

我们使用scaleOrdinal来得到从标签到颜色的映射,对于标签我们需要进行一定的排序处理,而颜色区间d3有现成的函数可以让我们很方便的得到渐变的颜色从而区分不同的等级。

我们可以搜索d3-scale-chromatic,里面有很多函数。在这里我们选择schemeSpectral[k],这个k是标签分类的个数,我们可以直接得到:

const colorValue = d => d.properties.income_grpconst colorScale = scaleOrdinal().domain(countries.features.map(colorValue));colorScale.domain(colorScale.domain().sort().reverse()).range(schemeSpectral[colorScale.domain().length]);

制作好颜色标签以后就是在添加path的后面设置fill属性,我之前做的是随机选择一个颜色,这里就改为根据上面已经设置好的颜色尺得到对应的颜色。

Showing data from 2 attributes in tooltip

在得到好看的颜色以后,我们还希望对应的标签的内容可以改变,这一点很容易再到,只需要在设置text的时候加上对应的属性即可。

g.selectAll('path').data(countries.features).enter().append('path').attr('class', 'country').attr('fill', d => colorScale(colorValue(d))) .attr('d', pathGenerator)
.append('title')//添加title,然后鼠标放在上面就可以出现标题.text(d => d.properties.name + ':' + colorValue(d));

初步效果图如下:
在这里插入图片描述

Adding a color legend

我们还希望添加一个颜色图例,这样就可以很方便地知道什么颜色对应的是什么内容而不必要一一去看。根据上一节(数据可视化【十二】颜色图例和尺寸图例)我们制作的颜色图例,可以直接进行使用。
index.js

  colorLegendG.call(colorLegend, {colorScale,circleRadius: 8,spacing : 20,textOffset : 15,backgroundRectWidth: 250});

colorLegend.js中,图例有一个背景,通过添加一个矩形来实现

  const backgroundRect = selection.selectAll('rect').data([null]);const n = colorScale.domain().length;backgroundRect.enter().append('rect').merge(backgroundRect).attr('x', -circleRadius * 2).attr('y', -circleRadius * 2).attr('rx', circleRadius * 2).attr('width', backgroundRectWidth).attr('height', spacing * n + circleRadius * 3).attr('fill', 'white').attr('opacity', 0.8);

最后效果图:在这里插入图片描述
代码地址:https://vizhub.com/Edward-Elric233/635845fd4c8b4917b999b18cab5e9b09

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383600.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据可视化【十四】交互式过滤地区分布图

在前面的博客中已经介绍了如何绘制地区分布图,这一节学习如何绘制交互式过滤地区分布图。如果对绘制地区分布图还不熟悉的话可以了解一下之前我写的博客:数据可视化【十三】地区分布图 整体的框架仍然是在之前的基础上进行修改,主要是添加交…

Ubuntu环境搭建

本文记录了一些常用的Ubuntu软件 然后首先修改软件源:软件和更新->Ubuntu软件->下载自:其他站点(修改为阿里云) 在关闭的时候需要更新什么的 然后修改更新方式,将不支持的更新去掉 常用的Windows软件 网易云…

Ubuntu修改/删除主目录下的中文文件夹

在Ubuntu的主目录下一般是有一些中文的目录,例如桌面,视频等等,还无法修改名称,在一群英文文件夹里面显得有些突兀(Ubuntu终端下的中文一点也不好看),就想把这些文件夹修改一下,结果…

每日一题:leetcode1489. 找到最小生成树里的关键边和伪关键边

时隔多年我终于又开始写博客了,主要是已经放假了,之前一直忙于考试和课设没有时间写博客,学习笔记也因为买了iPad的缘故大部分都是手写的了。 假期想要把以前做过的项目都整理一下放在github和CSDN上。 也已经很久没有写算法题了&#xff0…

每日一题:leetcode989.数组形式的整数加法

题目描述 题目分析 题目非常简单&#xff0c;但是我还是wa了几发&#xff0c;对不起&#xff0c;我太菜了。我的想法是把K转换为数组然后用大整数加法处理。但是因为太久没有写了导致写了好久。 class Solution { public:void add(vector<int> &A, vector<int&g…

每日一题:leetcode674.最长连续递增序列

题目描述 题目分析 一遍遍历&#xff0c;如果硬要说用了什么算法的话觉得应该算是一个简单的滑动窗口吧 AC代码 class Solution { public:int findLengthOfLCIS(vector<int>& nums) {if (nums.size() 0) {return 0;}int ret 1;int cnt 1;for (int i 1; i <…

每日一题:leetcode959.由斜杠划分区域

题目描述 题目分析 仔细分析这道题以后虽然觉得可能要转化为图之类的&#xff0c;但是完全没有具体的想法&#xff0c;因为每个格子都有三种情况&#xff0c;这三种情况的不同的组合又会产生不同的结果。 发现找不到编码转化为图以后&#xff0c;我分析了一下不同数量方块之间…

每日一题:leetcode1319.联通网络的操作次数

题目描述 题目分析 ps&#xff1a;这篇博客是补前天的&#xff0c;前天在老家不方便写博客 题目挺简单的&#xff0c;但是通过题目对图的连通性有了一个更深刻的认识&#xff1a;如果有超过&#xff08;或等于&#xff09;n-1条边&#xff0c;则一定是可以让整个图联通的。 如…

每日一题:leetcode1128.等价多米诺骨牌对数

题目描述 题目分析 看到题目以后第一个想法是遍历数组&#xff0c;对每个元素有一个数据结构中保存了该元素出现的次数&#xff0c;然后往结果中相加&#xff08;表示该元素和前面的对数&#xff09;&#xff0c;然后再将元素出现的次数加一。 思考用什么数据结构保存元素出现…

每日一题:leetcode1579.保证图可完全遍历

题目描述 题目分析 非常惭愧&#xff0c;感觉自己有点畏难心理&#xff0c;看到是困难题第一个想法是自己想不出来。。。 因为自己认为自己做不出来&#xff0c;所以完全不能进行思考&#xff0c;稍微思考一下就觉得不行不行。 我也想到了分别用两个并查集判断各自可以去掉多少…

每日一题:leetcode724.寻找数组的中心索引

题目描述 题目分析 今天这道题原本很简单&#xff0c;我都没打算写题解&#xff0c;当时用手机看的题目&#xff0c;我想着我三分钟应该能写出来&#xff0c;结果没想到wa了三发。。。 对待简单题不要轻视&#xff0c;对待难题不要畏难。 今天的主要问题是没有看数据范围&…

z3 C++学习笔记

因为项目需要使用z3库来解决问题&#xff0c;所以自己学习了一下&#xff0c;结果发现网上教程比较少&#xff0c;而且大部分都是使用Python&#xff0c;而我本人是C的忠实信徒&#xff0c;在知道C也可以使用z3库以后我毫不犹豫地着手用C使用z3&#xff0c;但是我很快发现&…

每日一题:leetcode191.位1的个数

题目描述 题目分析 很自然地想到了二进制枚举&#xff0c;直接循环检查每一个二进制位。 class Solution { public:int hammingWeight(uint32_t n) {int ret 0;uint32_t t 1;for (int i 0; i < 32; i, t << 1) {if (n & t) {ret;}}return ret;} };AC之后看了…

每日一题:leetcode341.扁平化嵌套列表迭代器

题目描述 题目分析 这个题目自己大概花了一个小时&#xff0c;虽然是一遍AC&#xff0c;但是速度有点慢&#xff0c;太长时间不写代码导致自己对代码不太敏感&#xff0c;写起来慢腾腾的。 看到这个的想法就是&#xff0c;要用栈来保存列表的迭代器&#xff0c;这样将孩子列表…

每日一题:leetcode82. 删除排序链表中的重复元素 II

题目描述 题目分析 这才是正常的中等题难度嘛&#xff0c;昨天的中等题题解我半天看不懂。。。 首先&#xff0c;需要增加一个哑节点&#xff08;操作链表的常规操作&#xff09;&#xff0c;因为有可能删除首节点&#xff0c;我们不想要为首节点添加单独的逻辑。其次&#xf…

每日一题:leetcode456.132模式

题目描述 题目分析 我觉得这道题应该是我做过最难的中等题之一了&#xff0c;这是昨天的每日一题&#xff0c;但是昨天用nlogn的做法做出来以后在看题解&#xff0c;发现有些看不懂&#xff08;觉得题解有点故弄玄虚&#xff09;。然后今天中午又花了一点时间才搞懂&#xff0…

leetcode283.移动零

题目描述 题目分析 在写简单题放松&#xff0c;看到这道题第一个想法是用STL库函数&#xff0c;虽然知道大概要用双指针之类的&#xff0c;但是库函数爽哇。 class Solution { public:void moveZeroes(vector<int>& nums) {stable_sort(nums.begin(), nums.end(), …

每日一题:leetcode61.旋转链表

题目描述 题目分析 很容易发现&#xff0c;如果k是n的整数倍&#xff0c;相当于没有移动。这样直接对k%n使得k在一个可以接受的范围。 因为是顺序移动&#xff0c;各元素之间的相对位置保持不变&#xff0c;所以就想着将链表先变成一个环。然后再移动头指针&#xff0c;最后再…

每日一题:leetcode173.二叉搜索树迭代器

题目描述 题目分析 更加地觉得编程重要的不在于如何写代码&#xff0c;用什么具体的技巧&#xff0c;编码本身只是一种将思维呈现的方式&#xff0c;但是如果思维是不清晰的&#xff0c;那么就算懂得再多的编码的奇技淫巧也是没有什么帮助的。相反&#xff0c;如果有一个清晰的…

leetcode11.盛最多水的容器

题目描述 题目分析 看到题目后第一个想法当然是O(n2)O(n^2)O(n2)的&#xff0c;但是数据范围是3e4&#xff0c;应该会超时&#xff0c;而且这种数据范围也不是让暴力求解的 。 相当于求解∑i<jmax((j−i)∗min(a[i],a[j]))\sum_{i<j}{max((j-i)*min(a[i],a[j]))}∑i<…