Skip to content
On this page

分析-哲学流派的“组织架构”是啥样的?


本章我们将会使用可视化完成 “哲学家和哲学流派的关系,哪些哲学家属于同一个流派?” 这个分析任务。

任务分析

首先我们需要拿到哲学家以及对应的哲学流派的关系数据,然后用一种可以表示包含关系的图表来进行可视化展示。

  • 将哲学家以及关联的哲学流派的数据关联起来,获得要分析的数据
  • 使用 CirclePacking 对数据进行可视化,通过这种图形嵌套的方式可以很好地看清数据的层次关系
  • 获取数据洞察

可视分析

获取数据

相关数据在 Github 上(哲学流派哲学家 以及 哲学家和哲学流派的关系数据)

用 Sparrow 绘制 CirclePacking

在绘制 CirclePacking 之前,我们需要了解 CirclePacking。

CirclePacking 也称为圆形树图,是矩阵树图的变体。它的图元使用的是圆圈而不是矩形,每个分支都表示为圆,其子分支表示为其内部的圆。每个圆的区域也可用于表示额外的任意值,如数量或文件大小,数值越大,圆的区域大小越大。

此外,颜色也可以用于分配类别或通过不同的色调表示另一个变量。

CirclePacking 不像矩阵树图那样空间效率高,因为圈子里有很多空位。尽管如此,CirclePacking 实际上揭示了比矩阵树图更好的层次结构。

和力导向图一样,Sparrow 也没有实现 CirclePacking 的布局算法,所以这里我们使用 d3-hierarchy 里面相关的布局算法。

image.png

javascript
(async () => {
  // 请求数据
  const URLS = [
    "https://gw.alipayobjects.com/os/bmw-prod/d345d2d7-a35d-4d27-af92-4982b3e6b213.json",
    "https://gw.alipayobjects.com/os/bmw-prod/188bb992-7a9b-4e0e-a036-d1d0e4269738.json",
    "https://gw.alipayobjects.com/os/bmw-prod/61a39597-9564-4f7e-9eb3-3bdd2280061d.json",
  ];
  const [people, schools, relations] = await Promise.all(
    URLS.map(async (url) => {
      const response = await fetch(url);
      return await response.json();
    })
  );

  // 将表格数据转换成层次数据
  const sidPid = d3.group(
    relations.filter((d) => d.type === "0"),
    (d) => +d.from
  );
  const pidData = d3.group(people, (d) => +d.id);
  const name = (d) => {
    const { name } = d.data;
    return name.length > 4 ? name.slice(0, 3) + "..." : name;
  };
  const data = {
    name: "哲学家",
    children: schools
      .filter(({ id }) => sidPid.has(id))
      .map(({ name, id }) => ({
        name,
        children: Array.from(sidPid.get(id)).map((d) => {
          const [people] = pidData.get(+d.to);
          return {
            name: people.name,
          };
        }),
      })),
  };

  // 计算布局
  const width = 800;
  const height = 800;
  const margin = 5;
  const padding = 5;
  const root = d3.hierarchy(data);
  root.count();

  const descendants = root.descendants();
  d3
    .pack()
    .size([width - margin * 2, height - margin * 2])
    .padding(padding)(root);
   
  // 绘制
  return sp.plot({
    type: "layer",
    data: descendants,
    width,
    height,
    guides: {
      x: { display: false },
      y: { display: false },
      color: { display: false },
    },
    scales: {
      r: { type: "identity" },
      x: { domain: [0, width - margin * 2] },
      y: { domain: [0, height - margin * 2], range: [0, 1] },
    },
    encodings: {
      x: "x",
      y: "y",
    },
    children: [
      {
        type: "point",
        paddingLeft: margin,
        paddingRight: margin,
        paddingBottom: margin,
        paddingTop: margin,
        encodings: {
          r: "r",
          stroke: "height",
          fill: "height",
        },
      },
      {
        type: "text",
        transforms: [(data) => data.filter((d) => d.height === 0)],
        encodings: {
          text: name,
        },
        styles: {
          textAnchor: "middle",
          dy: "0.5em",
        },
      },
    ],
  });
})();

Sparrow 虽然可以如上去绘制 CirclePacking,但是还是会比较麻烦,接下来我们就用 AntV 的 G2Plot 去实现相同的效果。

G2Plot 绘制 Circle Packing

了解之后,我们可以直接使用 G2Plot CirclePacking 来进行绘制:

  1. 数据处理成树型结构。处理完成的数据结构大概如下:
    
javascript
const data = {
  name: "哲学家",
  children: [
    { 
      name: "自然学派",
      children: [
        { name: "泰利斯", value: 1 },
        { name: "安纳克西曼德", value: 1 },
        // ...
      ]
    },
    { 
      name: "雅典的哲学",
      children: [
        { name: "普罗塔格拉斯", value: 1 },
        { name: "苏格拉底", value: 1 },
        // ...
      ]
    },
    {
      name: "希腊哲学",
      children: [
        { name: "第欧根尼", value: 1 },
        { name: "伊壁鸠鲁", value: 1 },
        // ...
      ]
    },
    // ...
  ]
}
  1. 使用 G2Plot 绘制

在这里,我们按照分类的大小 r(数据中对应的是 r 字段对应的数值) 来设置颜色,以增强区分度:

javascript
// 前提,需要有一个图表容器: html`<div id="container"></div>`
const plot = new G2Plot.CirclePacking('container', {
  width: 600,
  height: 600,
  appendPadding: 30,
  autoFit: true,
  padding: 0,
  data: getCirclePackingData(),
  colorField: 'r',
  color: 'rgb(252, 253, 191)-rgb(231, 82, 99)-rgb(183, 55, 121)',
  pointStyle: {
    stroke: 'rgb(183, 55, 121)',
    lineWidth: 0.5
  },
  legend: false
});

plot.render();

数据洞察

下图是绘制出来的可视化结果:

从中我们可以洞察到:

  • 绝大多数的哲学家倾向于“自然学派”(最大的那个圆,对应的颜色也是最深的)。
  • 而类似于“共产主义”、“存在主义”、“理性主义”和“个人主义”代表的哲学家就相对较少。

延伸

G2Plot

G2Plot 是基于 G2 封装的开箱即用、易于配置、具有良好视觉和交互体验的通用统计图表库。它主要以图表分类学的角度去封装,既减少用户理解图形语法的成本、降低上手门槛,也基于 AntV 的可视化设计原则做了交互体验优化。

G2Plot 的核心技术架构非常简单,所有的 Plot 图表都继承于一个基类,基类为所有的图表提供的了通用的 API 方法,而每个具体的可视化图表仅仅处理自己不同的配置项。所以 API 部分,所有图表基本都是一样,除了部分图表(比如:仪表盘、水波图)在 changeData API 上有细微的区别。

如果想了解更多,可以去阅读 G2Plot 官网教程,官网也提供了较多的案例 demo,方便业务直接取用自己需要的图表。

小结

这一章我们探索了:“哲学流派的“组织架构”是啥样的?”,又了解一种可视化层次数据的办法。那么下一章我们去探索:“西方哲学中心的“迁徙之旅”,同时简单了解一下地理可视化相关的东西。