Skip to content
On this page

分析-抽象的哲学问题又有谁来解?


本章我们将会使用可视化完成 “苏菲的世界中,问题和哲学家之间的关系是怎样的?” 这个任务。也就是看看哪些哲学家回答了哪些抽象的哲学问题。

任务分析

这个问题需要分析哲学和问题之间的关系,分成几步:

  • 罗列出哲学家和问题,然后将问题和哲学家进行连接, 使用力导图对问题和参与该问题的哲学家进行可视化
  • 蓝色代表问题,绿色代表哲学家,连线代表哲学家参与了该问题
  • 获取数据洞察

前述从 0 到 1 开发的极简统计图表, 由于力导图的实现相对复杂,这里我们直接用 AntV 成熟的图可视化引擎 G6 来绘制和完成任务。

下面会按照这几个步骤,去实现这样的一个力导图,并从中获得数据洞察。

可视分析

获取数据

首先我们从《苏菲的世界》中,获取所有问题列表,以及回答过该问题的哲学家,为了简化代码,我们仅列出少量数据和有代表性的数据项,全量数据可在 GitHub 上下载。

ts
// 哲学家列表
const philosophers = [
  {
    name: "泰利斯",
    id: "66",
  },
  // ...
];
// 问题列表
const questions = [
  {
    title: "世界从何而来?",
    id: "0",
  },
  {
    title: "我是谁?",
    id: "1",
  },
];
// 关系列表
const relations = [
  { from: "151", to: "66" },
  // ...
];

用 Sparrow 绘制力导向图

力导向图是图可视化的一种,通过算法模拟自然界的引力和斥力去给图中的节点布局。和词云图一样,Sparrow 也没有实现力导向布局算法,所以这里我们用 d3-force 去计算布局,然后再用 Sparrow 去绘制。

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/3df5a34b-9141-453b-b1c9-5dd0eba32273.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, questions, schools, relations] = await Promise.all(
    URLS.map(async (url) => {
      const response = await fetch(url);
      return await response.json();
    })
  );

  // 把扁平的数据转化成嵌套的数据
  const qidPid = d3.group(
    relations.filter((d) => d.type === "1"),
    (d) => +d.from
  );
  const pidData = d3.group([...people, ...schools], (d) => +d.id);
  const data = {
    name: "永恒的问题",
    type: "问题",
    children: questions
      .filter(({ id }) => qidPid.has(id))
      .map(({ title, id }) => ({
        name: title,
        type: "问题",
        children: Array.from(qidPid.get(id)).map((d) => {
          const [people] = pidData.get(+d.to);
          return {
            name: people.name,
            type: "哲学家",
          };
        }),
      })),
  };

  // 计算布局
  const root = d3.hierarchy(data);
  const links = root.links();
  const nodes = root.descendants();
  const simulation = d3
    .forceSimulation(nodes)
    .force(
      "link",
      d3
        .forceLink(links)
        .id((d) => d.id)
        .distance(0)
        .strength(1)
    )
    .force("charge", d3.forceManyBody().strength(-50))
    .force("x", d3.forceX())
    .force("y", d3.forceY())
    .stop();

  // @see https://bl.ocks.org/mbostock/1667139
  // compute a static force layout
  const n = Math.ceil(
    Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())
  );
  for (let i = 0; i < n; ++i) {
    simulation.tick();
  }

  // 绘制
  return sp.plot({
    type: "layer",
    guides: {
      x: { display: false },
      y: { display: false },
    },
    children: [
      {
        type: "link",
        data: links,
        encodings: {
          x: (d) => d.source.x,
          y: (d) => d.source.y,
          x1: (d) => d.target.x,
          y1: (d) => d.target.y,
          stroke: "#ddd",
        },
      },
      {
        type: "point",
        data: nodes,
        encodings: {
          x: "x",
          y: "y",
          r: 10,
          fill: (d) => d.data.type,
          stroke: (d) => d.data.type,
        },
        styles: {
          fillOpacity: 0.7,
        },
      },
    ],
  });
})();

Sparrow 虽然可以快速绘制简单的力到导向图,但是不能展示每个节点的具体信息,所以接下来我们使用 AntV 的 G6 去绘制力导向图。

用 G6 绘制力导向图

在绘制力导图之前,我们需要简单了解一下 G6。G6 是图可视化引擎,它通过:

  1. 通过多种图展现形式,让关系变得透明、简单
  2. 多种视觉盛宴,让用户获得关系数据的 Insight
大规模图下钻探索模式图说“水深火热”的澳大利亚道

接下来我们分两步绘制力导图。

  • 数据组装

由于 G6 对数据格式有一定的限制,我们需要将上面获取到的哲学家列表、问题列表和关系列表进行简单组装,输出为 G6 所需的 nodes 和 edges,通过颜色区分哲学家和问题。 我们将关系列表作为边,其它的作为节点,详细转换见线上 Demo。

  • 哲学家:绿色节点 #BDEFDB
  • 问题:蓝色节点 #BDD2FD
ts
const data = {
  nodes: [
    {
      id: "66",
      style: { fill: "#BDEFDB" },
    },
    {
      id: "151",
      style: { fill: "#BDD2FD" },
    },
  ],
  // 需要将 from、to 转换为 source、target
  edges: [
    {
      source: "151",
      target: "66",
    },
  ],
};
  • 使用 G6 绘制力导图

有了前面的准备工作,绘制力导图就很容易了。

ts
import { G6 } from "@antv/g6";

// 1. 创建图表容器
const graph = new G6.Graph({
  container: "container",
  width: 800,
  height: 600,
  layout: {
    type: "force",
    preventOverlap: true,
  },
});
// 2. 转载第一步中处理好的数据
graph.data(data);
// 3. 渲染
graph.render();

最后绘制出来的效果如下图所示。

数据洞察

从中我们可以获取一些有效信息和洞察:

  • 一个哲学家/学派可能对多个问题感兴趣。
  • 有趣的问题往往能吸引更多哲学家。

延伸

图布局

可视化是一种利用计算机图形学和图像处理技术,将数据转换成图形或图像在屏幕上显示出来,再进行交互处理的理论、方法和技术。数据在经过图可视化的方式展示后能够辅助用户去分析复杂的关系数据,从而发现数据中蕴含的价值。而图布局则是图可视化中非常重要的基石,对可视化图进行合理的布局可以帮助我们快速分析,准确定位问题。

在可视化领域中常见的布局有树形布局、Dagre 布局、力导布局、同心圆布局、网格布局等。

布局方案适用场景示例
力导布局适用于描述事物间关系,比如社交网络关系、计算机网络关系、资金交易关系等各类关系网络场景image.png
网格布局节点按一定排序网状排开,适应于分层网络,便于看清整体层次image.png
同心圆布局将节点按照度数排序,节点度数大的一群点会排列在最中心,度数小的节点会分布在最外层,使其以同心圆的方式排布,适应于快速查找出度数较多的节点image.png
圆形布局适用于查找关联关系较多的关键节点场景,例如在圆形布局的图中可以明显分辨出哪些节点关联关系较多image.png
树形布局 / Dagre布局适应于层次分明,或者需要严密拓扑性质的场景,比如分层网络图、流程图等image.png

G6

AntV G6 是一款开源的图可视化引擎,专注于图可视化及图分析,使用 G6,你可以发挥无限想象,创造出炫酷的图可视化。中文字“图”在大家的传统认知里指的是图画、图像,而图论与可视化中的“图”—— Graph 则有着更精确的定位:主体(objects)与关系(relationships)的组成。它甚至不局限于视觉,主体与关系的数据也可以称为图。

摘自文章:Graph Visualization · 知多少 之 《HelloWorld 图可视化》。

在 G6 中,Graph 对象是图的载体,它包含了图上的所有元素(节点、边等),同时挂载了图的相关操作(如交互监听、元素操作、渲染等)。

Graph 对象的生命周期为:初始化 —> 加载数据 —> 渲染 —> 更新 —> 销毁。

同时,G6 里面内置了大量的布局算法,例如模式匹配、最短路径、LOUVAIN 自动类聚等。

如果想了解更多,可以去阅读 G6 官网教程,未来将会发表的学术论文,更详细体系的介绍它的技术模块和架构。

小结

这一章我们知道了:“抽象的哲学问题又有谁来解?”,也简单认识了一下图可视化,那么接下来我们将继续探索下一个问题:“哲学流派的“组织架构”是啥样的?”