“数”说亚运会!G2 带你盘点亚运会“冷知识”

avatar
数据可视化 @蚂蚁集团

语雀地址

10月8日,第19届杭州亚运会在数字人的比心中顺利闭幕了。在过去的十几天中,亚洲各国的运动健儿顽强拼搏,赛出了友谊,也赛出了风采。

image.png

为了更好的了解参加亚运会的运动员,我们收集所有参赛选手的信息,包含姓名、国籍、年龄和获得金牌数等,然后用 G2 对其进行了简单的可视化探索。

image.png

那么接下来我们就来了解整个流程和最后的可视化结果吧!完整的可视化分析页面和代码在这里

数据收集

首先是数据的收集。我们收集的运动员数据来自于亚运会官网,该数据是一份如下的表格数据:

image.png

每一列对应一位运动员,一共有11808位运动员的信息,这里简单介绍一下每个字段的含义:

  • birthday:运动员的生日
  • gender:运动员的性别
  • age:运动员的年龄
  • height:运动员的身高,单位为米
  • name:运动员的姓名
  • sport:参加的运动项目名字
  • gold:该运动员获得的金牌数
  • silver:该运动员获得的银牌数
  • bronze:该运动员获得的铜牌数
  • code:运动员的唯一 id
  • noc:国家的缩写
  • org:国家的编号
  • dis:参加的运动项目名字的缩写
  • img_id:图片的 id

选择可视化工具

在获得了数据之后,就需要选择我们的可视化工具了:这里我们选择了 AntV 的 G2

选择 G2 的原因是在其 5.0 版本中提供了 transform API ,内置了一系列数据探索的方法,可以方便地对原始数据进行聚合、筛选、排序等。同时增强了分面的能力,可以高效地探索数据的子集。

在开始分析探索前,我们封装一个工具方法,使得声明图表更加的简单。想了解更多 G2 的使用方法,可以去其 github 仓库。

function g2(options) {
  const chart = new G2.Chart(); // 初始化图表
  chart.options(options); // 声明可视化
  chart.render(); // 渲染可视化
  return chart.getContainer(); // 返回并且挂载容器
}

那么接下来,我们就用这个 g2 方法去探索我们收集的数据 data。

问题0:分布

我们首先从一个简单的任务开始,只探索数据的一个维度:height,看看运动员的高度是分布如何。

这里我们使用了 point mark 去绘制了一个散点图,因为运动员的数量较多,所以这里我们设置了点的 fillOpacity 来缓解 overplotting 的问题。在这样的情况下,颜色越深的区间,运动员的数量较多;颜色越浅的区间,运动员的数量较少。下面是我们可视化的结果:

image.png

g2({
  type: "point",
  data,
  height: 120,
  encode: { x: "height" },
  style: { shape: "point", fillOpacity: 0.2 },
  tooltip: { title: "name" }
})

可以发现大部分运动员的身高在1.6m到2m这个区间,最矮的运动员居然只有80cm,姓名是雷斯别克·托洛穆舍夫,是吉尔吉斯斯坦的一名皮划艇静水运动员,不知道是不是数据录入有误;最高的运动员是2.2m,是中国的一名篮球运动员。

当然我们也可以通过 boxplot mark 去绘制一个箱线图,更直观地了解运动员身高的分布。

image.png

g2({
  type: "boxplot",
  data,
  coordinate: { transform: [{ type: "transpose" }] },
  height: 120,
  encode: { y: "height" }
})

问题1:相关性

完成了第一个比较简单的任务。那么接下来我们稍稍加大一点难度,这一次同时我们分析数据的三个维度:gender、sport 和 height。看看在考虑性别的情况下,运动项目和身高之间的相关性。比如什么运动的运动员身高相对较高?

这里我们同样可以使用 point mark,只不过需要对其 x,y 和 color 通道都进行编码,然后按照身高中位数进行排序。同时需要根据运动项目的数量动态计算图表高度。当然,为了更清晰的观察每个运动高度区间,我们在每个运动身高最矮和身高最高的运动员之间连一条线,最后得到如下的点线连接图:

image.png

g2({
  type: "view",
  width: 800,
  // 去掉异常数据
  data: data.filter((d) => d.height !== 0.8 && d.height !== null),
  // 动态计算图表高度
  height: new Set(data.map((d) => d.sport)).size * 20,
  coordinate: { transform: [{ type: "transpose" }] },
  encode: {
    x: "sport",
    y: "height"
  },
  scale: { y: { nice: true } },
  axis: { y: { title: "height" } },
  children: [
    {
      type: "link",
      encode: { y1: "height" },
      // 按照 x 通道(height)分组,
      // 最小值为 y 通道,最大值为 y1 通道
      transform: [{ type: "groupX", y: "min", y1: "max" }],
      style: { strokeOpacity: 0.4, stroke: "black" },
      tooltip: null
    },
    {
      type: "point",
      encode: { color: "gender" },
      // 按照 median 中位数排序
      transform: [{ type: "sortX", by: "y", reducer: "median", reverse: true }],
      style: { shape: "point", fillOpacity: 0.2 }
    }
  ]
})

可以发现篮球和排球的运动员都普遍较高,这也符合这些运动选拔运动员的标准。同时我们可以注意到,每项运动越偏右越蓝,而蓝色代表男性,说明参加比赛的男性运动员普遍比女性运动员高。另外通过观察不同运动的 link 长度,可以发现,篮球、板球等的运动员的身高差距较大,而高尔夫、马拉松游泳等运动员的身高差距较小。

问题2:计数

上面的两个任务我们都是在分析每个运动员,属于单元可视化。接下来我们来看一些和计数相关的任务,比如第一个问题:每个国家有多少人来参加了亚运会,哪个国家最多?性别比例又是怎样的?

这里我们可以用 interval mark 去绘制一个条形图,并且将数据按照国家分组之后求和,同时对结果进行堆叠和排序,最后得到一个聚合有序的堆叠条形图。下面是我们的可视化结果:

image.png

g2({
  type: "interval",
  width,
  data,
  encode: { x: "nation", color: "gender" },
  transform: [
    { type: "groupX", y: "count" }, // 按照 x 通道分组,将求和结果作为 y 通道的值
    { type: "stackY", orderBy: "series" }, // y 通道堆叠,同时按照性别排序
    { type: "sortX", by: "y", reverse: true } // 对 x 通道进行排序,按照 y 的大小
  ],
  scale: { y: { nice: true } },
  tooltip: { title: "nation" }
})

比较出人意料的是,中国并不是参赛选手最多的国家,最多的居然是泰国!同时有一个很有意思的现象:参赛人数越多的国家,参赛运动员的男女比例越平衡;参赛人数越少,男性参赛选手越多。比如前几名泰国、中国和韩国等国家蓝色和绿色的高度几乎一半一半,但是叙利亚、伊拉克和不丹等没有和几乎没有绿色的条。

接下来我们来看看,每个运动项目有多人参赛?性别比例又如何?

这里为了更清晰地反映男女之间的差异,我们使用一个发散条形图(Diverging Bar Chart)。这同样需要我们对数据进行分组聚合,只不过在这之前我们需要分别用 1 和 -1 代表单个男和女运动的数量,同时在聚合之后需要根据数量的绝对值进行排序。下面是我们最后可视化的结果。

image.png

g2({
  type: "interval",
  data,
  width,
  height: 20 * new Set(data.map((d) => d.dis)).size,
  coordinate: { transform: [{ type: "transpose" }] },
  encode: {
    x: "sport",
    color: "gender",
    y: (d) => (d.gender === "男" ? 1 : -1) // 向两边求和
  },
  transform: [
    // 按照 x 通道值分组,将每一项的 y 通道求和作为组的 y 通道
    { type: "groupX", y: "sum" }, 
    // 根据绝对值求和排序
    {
      type: "sortX",
      by: "y",
      reverse: true,
      reducer: (I, V) => d3.sum(I, (i) => Math.abs(V[i])) 
    }
  ],
  scale: { y: { nice: true } },
  axis: {
    y: {
      title: "← female · male →",
      labelFormatter: (d) => `${Math.abs(+d)}` // 显示绝对值
    }
  },
  tooltip: {
    title: "sport",
    items: [{ channel: "y", valueFormatter: Math.abs }]
  }
})

可以发现参赛运动员较多的是足球和田径,不愧是运动大项。电子竞技的参赛人数如此之多还挺意外的。同时可以发现大部分运动的男女比例都相对平衡的,但是也有一些运动看上去不太平衡:

  • 电子竞技男性很多,女性很少。
  • 棒球只有男性,垒球只有女性。当然这个两个项目本来就比较特殊,男性参加的叫棒球,女性参加叫垒球。
  • 花样游泳几乎没有男性。花样游泳之前是只能女性参加的,这几年男性也可以参加了,同时本届亚运会也是第一届允许男性参加花样游泳的亚运会。
  • 艺术体操只有女性。

问题3:出生年份

现在我们来关注 birthday 这个字段,来看看参加本次运动会的运动员都是什么时候出生的?

这里我们需要使用 rect mark,在使用 binX 对数据进行分箱之后,需要使用 stackY 对数据进行堆叠。需要注意的是,原始数据里面有一些脏数据:1900年出生和2020年之后出生的,这些我们都需要先过滤掉。最后就得到了如下的一个堆叠直方图:

image.png

g2({
  type: "rect",
  width: 800,
  // 过滤掉脏数据
  data: data.filter((d) => {
    const year = new Date(d.birthday).getFullYear();
    return year !== 1900 && year < 2020;
  }),
  encode: {
    x: (d) => new Date(d.birthday).getFullYear(), // 获取出生年份
    color: "gender"
  },
  transform: [
    { type: "binX", y: "count" }, // 对 x 通道进行分箱,求和之后最为每组的 y 通道
    { type: "stackY", orderBy: "series" }
  ],
  style: { inset: 0.5 },
  axis: { x: { title: "birthyear", tickCount: 20 } }
})

可以发现大部分运动员都是2000左右出生的,其中年龄最大的运动员大概是1940年出生的,现在已经80多岁了,是象棋运动员,而最年轻的运动员大概是15年左右出生的,目前才10岁左右,是滑板运动员。不得不感叹亚运会对年龄的包容性。

我们还可以看看每个年龄段的获奖情况,人数越多的组对应的条在越上面。

image.png

g2({
  type: "rect",
  width: 800,
  data: data.filter((d) => {
    const year = new Date(d.birthday).getFullYear();
    return year !== 1900 && year < 2020;
  }),
  encode: {
    x: (d) => new Date(d.birthday).getFullYear(),
    color: (d) =>
      d.gold !== 0
        ? "金牌"
        : d.silver !== 0
        ? "银牌"
        : d.bronze !== 0
        ? "铜牌"
        : "无牌"
  },
  transform: [
    { type: "binX", y: "count" },
    { type: "stackY", orderBy: "value" }
  ],
  scale: {
    color: {
      domain: ["金牌", "银牌", "铜牌", "无牌"],
      range: ["#F6BD16", "#5D7092", "#CE8032", "#eee"]
    }
  },
  style: { inset: 0.5 },
  axis: { x: { title: "birthyear", tickCount: 20 } }
})

问题4:年龄和奖牌

上一个任务我们探索了出生日期,接下来我们来看看一个相关的维度:age 和奖牌之间的相关性。因为所有参赛运动员太多了,所以这里我们只关注中国的运动员。

因为涉及到了相关性,所以这里我们还是用 point mark 去绘制一个散点图,这次我们用获奖情况去编码颜色通道。同样为了考虑性别因素,我们让点向两边发散堆叠,从而得到了如下的一个发散堆叠散点图:

image.png

g2({
  type: "view",
  width: 800,
  coordinate: { transform: [{ type: "transpose" }] },
  children: [
    {
      type: "point",
      data: data
        .filter((d) => d.noc === "CHN")
        .map((d) => ({
          ...d,
          medal:
            d.gold !== 0
              ? "金牌"
              : d.silver !== 0
              ? "银牌"
              : d.bronze !== 0
              ? "铜牌"
              : "无牌"
        })),
      encode: {
        x: "age",
        y: (d) => (d.gender === "男" ? 1 : -1),
        color: "medal",
        shape: "point"
      },
      scale: {
        x: { nice: true },
        color: {
          domain: ["金牌", "银牌", "铜牌", "无牌"],
          range: ["#F6BD16", "#5D7092", "#CE8032", "#eee"]
        }
      },
      axis: {
        y: {
          title: "← female · male →",
          labelFormatter: (d) => `${Math.abs(+d)}`
        }
      },
      transform: [
        {
          type: "stackY",
          y1: "y",
          // orderBy: "series"
          orderBy: (d) => {
            const medals = ["金牌", "银牌", "铜牌", "无牌"].reverse();
            const index = medals.indexOf(d.medal);
            return d.gender === "男" ? index : -index;
          }
        }
      ],
      tooltip: {
        title: "name",
        items: [
          { field: "gold" },
          { field: "silver" },
          { field: "bronze" },
          { field: "age" }
        ]
      }
    },
    { type: "lineY", data: [0], style: { stroke: "black" } }
  ]
})

这图能获得不少有意思的信息。首先有和上一个分析任务的一致的结论:大部分参赛运动员都是2000年左右出生,所以中国大部分参赛运动员的年龄是在20到30岁之间。同时我们可以发现中国大部分女性运动员都获得了奖牌的,并且金牌获得者是最多的。相比下,男性运动员没有获得奖牌的就多不少,大概有一半左右。我们还可以发现中国的大龄运动员(40岁以上),大部分都是获得了奖牌的。

问题5:奖牌,国家和运动

上一个问题我们探索了中国个人的获奖情况,现在我们来看看每个国家和运动的获奖情况。哪些国家获和哪些运动获奖多?

因为国家和运动维度都是离散的,所以我们选择用 cell mark 绘制一个热力图,同时按照获奖人数的总数降序排序。颜色越深的块表示获奖越多,白色表示该国家的该项目没有人参加,灰色表示参加了但是没有获得任何奖牌。最后获得的可视化结果如下:

截屏2023-10-10 下午2.15.40.png

g2({
  type: "cell",
  width: 1100,
  height: 1000,
  data,
  encode: {
    x: "sport",
    y: "nation",
    color: (d) => d.gold + d.silver + d.bronze // 每个人的奖牌总数
  },
  transform: [
    { type: "group", color: "sum" }, // 按照 x 和 y 通道分组,并对颜色通道求和
    { type: "sortY", by: "color", reverse: true }, // y 通道排序
    { type: "sortX", by: "color", reverse: true } // x 通道排序
  ],
  // 将 0 设置为 #eee 灰色
  scale: { color: { relations: [[0, "#eee"]], palette: "puRd" } },
  style: { inset: 0.5 }
})

注意:这里的总数不是奖牌榜上的总数,而是得到产生的奖牌数,因为团队运动(足球、篮球等)的一枚奖牌在奖牌榜上只会算一次,但是上图中每一个获奖运动员都会算一次。

可以发现图中白色和灰色区域不少,说明大部分国家的大部分项目都没有参加或者获奖,但是我们得为这些国家的运动员送去最高的敬意。除此之外,我们可以发现中国获奖人数是最多的,而其中游泳队又傲视群雄。这自然而然就会引出另一个问题:每个国家参赛的人数越多,就获奖越多吗?

这里我们绘制一个点线连接图来解决这个问题。首先我们需要借助 group transform 将数据按照国家分组之后,分别聚合计算总参加人数和获奖人数。然后用 point mark 去表示每一个国家,同时用 link mark 绘制一条从原点到点的线代表斜率。不难得出,斜率越大的线对应的国家获奖率(获奖人数/总人数)更高。最后的结果如下:

image.png

g2({
  paddingRight: 16,
  type: "view",
  encode: {
    x: 1,
    y: (d) => (d.gold + d.silver + d.bronze === 0 ? 0 : 1),
    series: "nation"
  },
  transform: [{ type: "group", channels: "series", x: "sum", y: "sum" }],
  scale: {
    x: { nice: true },
    y: { nice: true }
  },
  axis: {
    x: { title: "number of participants" },
    y: { title: "number of winners" }
  },
  children: [
    {
      type: "link",
      data: [2 / 3, 1 / 3],
      encode: {
        x: [0, 1000],
        y: [0, (d) => d * 1000],
        series: (d, idx) => idx
      },
      style: { stroke: "#777" },
      labels: [
        {
          position: "top-right",
          text: (v) => `${v.toFixed(2) * 100}%`,
          dx: 4,
          textAlign: "start",
          textBaseline: "middle",
          fontSize: 10
        }
      ],
      tooltip: false
    },
    {
      type: "link",
      data,
      encode: { x1: 0, y1: 0 },
      style: { stroke: "#eee" }
    },
    {
      type: "point",
      data,
      labels: [
        {
          text: "nation",
          dy: 8,
          fontSize: 10,
          transform: [{ type: "overlapHide" }]
        }
      ]
    }
  ]
})

分析可以发现,总体的趋势确实是参赛人数越多获得得奖牌数越多。并且,中国不仅仅是获奖人数最多的国家,同时也是获奖效率最高的国家(斜率最大),日本和韩国也有不错的获奖效率,相对之下泰国的获奖效率就较低。

问题6:奖牌,身高和性别

通过上面一个任务我们可以发现中国的获奖数是最多的,那么接下来我们就聚焦分析中国队的得奖情况。首先我们来看看奖牌、身高和性别之间的关系。

这里我们可以用 facetRect 将数据按照获奖情况分成四个子集,分别用堆叠直方图看看身高的分布:

image.png

g2({
  type: "facetRect",
  width: 1000,
  height: 380,
  paddingLeft: 50,
  paddingBottom: 50,
  data: data
    .filter((d) => d.noc === "CHN") // 只关注中国
    .map((d) => ({ // 生成 medal 字段,表示获奖情况
      ...d,
      medal:
        d.gold !== 0
          ? "金牌"
          : d.silver !== 0
          ? "银牌"
          : d.bronze !== 0
          ? "铜牌"
          : "无牌"
    })),
  encode: { x: "medal" },
  scale: { x: { domain: ["金牌", "银牌", "铜牌", "无牌"] } }, // 排序
  children: [
    {
      type: "rect",
      encode: { x: "height", color: "gender" },
      transform: [
        { type: "binX", y: "count" }, // 分箱
        { type: "stackY", orderBy: "series" } // 堆叠
      ],
      style: { insetLeft: 0.5 }
    }
  ]
})

通过上图我们发现金牌、银牌、铜牌的身高分布大致相同,都是在1.7和1.8m左右的人数最多。但是无牌的运动员的身高普遍较高,大部分是在1.9m和2m之间,难道身高越高,越难获得奖牌?

问题7:统计

上一个问题我们分析了奖牌、身高和性别之间的关系,在这个任务中我们把身高这个维度换成年龄看看能得到什么结果。同样我们只关注中国队的情况。

除了改变一个分析维度之外,我们也在优化一下我们的分析方法。第一,我们可以对子集继续划分,比如按照性别这个维度。第二,我们可以用 lineX mark 结合 group transform 去绘制标注线,展现年龄的中位数。最后我们得到如下的一个二维的分面直方图:

image.png

g2({
  type: "facetRect",
  width: 1000,
  height: 560,
  paddingLeft: 50,
  paddingBottom: 50,
  data: data
    .filter((d) => d.noc === "CHN") // 只关注中国
    .map((d) => ({ // 生成 metal 字段
      ...d,
      medal:
        d.gold !== 0
          ? "金牌"
          : d.silver !== 0
          ? "银牌"
          : d.bronze !== 0
          ? "铜牌"
          : "无牌"
    })),
  encode: {
    x: "medal",
    y: "gender"
  },
  scale: {
    x: { domain: ["金牌", "银牌", "铜牌", "无牌"] },
    color: {
      // 设置颜色映射规则
      domain: ["金牌", "银牌", "铜牌", "无牌"],
      range: ["#F6BD16", "#5D7092", "#CE8032", "#eee"]
    }
  },
  children: [
    {
      type: "view",
      children: [
        {
          type: "rect",
          encode: { x: "age", color: "medal" },
          transform: [{ type: "binX", y: "count" }],
          scale: {
            color: {
              domain: ["金牌", "银牌", "铜牌", "无牌"],
              range: ["#F6BD16", "#5D7092", "#CE8032", "#eee"]
            }
          },
          style: { insetLeft: 0.5 }
        },
        { // 标注线
          type: "lineX",
          encode: { x: "age" },
          transform: [{ type: "groupColor", x: "median" }],
          style: {
            stroke: "#F4664A",
            strokeOpacity: 1,
            lineWidth: 2,
            lineDash: [4, 4]
          },
          labels: [ // 标注线文本
            {
              text: "age",
              position: "top",
              textBaseline: "top",
              textAlign: "start",
              dx: 5,
              dy: 5,
              stroke: "white",
              strokeWidth: 2
            }
          ]
        }
      ]
    }
  ]
})

可以发现获得金牌最多的年龄段是23岁,是不是意味着运动员的巅峰是23岁?男女在铜牌和无牌分布和中位数大致一致,但是男性运动员大部分是在31岁获得银牌的,女性是在22岁,这方面有较大的差异。

问题8:归约

接下来我们继续探索奖牌、年龄和性别之间的关系,只不过这一次问题可能要更加困难一点:有多少女运动员比获得该奖牌的最年轻的男性运动员小?又有多少女运动员比获得该奖牌的最年长的男性运动员大?同样我们只关注中国队的情况。

这次每一个视图我们用 point mark 去绘制一个散点图。其中女性运动员用彩色点表示,同时用一根彩色线标注年龄的中位数。男性运动员用深灰色点表示,同时用一根深灰色线标注线年龄的最小值,一根深灰色线线标注年龄的最大值。要回答上面的问题,我们只要关注有多少彩色的点在第一根深灰色线左边,和多个彩色的点在第二根深灰色线右边即可。最后我们获得可视化结果如下:

image.png

g2({
  type: "facetRect",
  height: 320,
  width: 800,
  paddingLeft: 5,
  paddingBottom: 50,
  data: data
    .filter((d) => d.noc === "CHN") // 只关注中国
    .map((d) => ({ // 生成获奖情况的字段
      ...d,
      medal:
        d.gold !== 0
          ? "金牌"
          : d.silver !== 0
          ? "银牌"
          : d.bronze !== 0
          ? "铜牌"
          : "无牌"
    })),
  encode: { y: "medal" },
  scale: {
    y: { domain: ["金牌", "银牌", "铜牌", "无牌"] },
    color: {
      domain: ["金牌", "银牌", "铜牌", "无牌"],
      range: ["#F6BD16", "#5D7092", "#CE8032", "#eee"]
    }
  },
  children: [
    {
      type: "view",
      scale: {
        color: {
          domain: ["金牌", "银牌", "铜牌", "无牌"],
          range: ["#F6BD16", "#5D7092", "#CE8032", "#eee"]
        }
      },
      children: [
        { // 标注最小的男性运动员
          type: "lineX",
          data: {
            transform: [{ type: "filter", callback: (d) => d.gender === "男" }]
          },
          encode: { x: "age" },
          transform: [{ type: "selectX", selector: "min" }],
          style: { stroke: "grey", strokeWidth: 3, strokeOpacity: 1 }
        },
        { // 标注最大的男性运动员
          type: "lineX",
          encode: { x: "age" },
          data: {
            transform: [{ type: "filter", callback: (d) => d.gender === "男" }]
          },
          transform: [{ type: "selectX", selector: "max" }],
          style: { stroke: "grey", strokeWidth: 3, strokeOpacity: 1 }
        },
        { // 标注女性运动员年龄的中位数
          type: "lineX",
          encode: { x: "age", color: "medal" },
          data: {
            transform: [{ type: "filter", callback: (d) => d.gender === "女" }]
          },
          transform: [{ type: "selectX", selector: "median" }],
          style: { strokeWidth: 3, strokeOpacity: 1 }
        },
        { // 男性运动员
          type: "point",
          data: {
            transform: [{ type: "filter", callback: (d) => d.gender === "男" }]
          },
          encode: { x: "age", size: 2 },
          style: { shape: "point", fill: "grey" }
        },
        { // 女性运动员
          type: "point",
          data: {
            transform: [{ type: "filter", callback: (d) => d.gender === "女" }]
          },
          encode: { x: "age", color: "medal", size: 3 },
          style: { shape: "point" }
        }
      ]
    }
  ]
})

可以发现在金牌、银牌和铜牌的视图中,都有彩色点在第一根深灰色的线左边,看来“自古英雄不仅仅出少年,现在巾帼也不让须眉”。同时在金牌的视图中,我们也可以看见有不少彩色点在第二根深灰色的线右边,为这几个优秀的女性运动员点一个大大的赞。

问题9:金牌

最后我们来探索一个比较“功利”和简单的问题:哪些运动员获得的奖牌数最多?

这里我们用 interval mark 绘制一个简单的条形图就可以了,最后的结果如下:

image.png

g2({
  type: "interval",
  height: 400,
  data: data.sort((a, b) => b.gold - a.gold).slice(0, 10),
  encode: {
    x: "name",
    y: "gold",
    color: "sport"
  },
  axis: {
    x: { labelFormatter: (d) => (d.length > 5 ? d.slice(0, 5) + "..." : d) }
  }
})

分析可得,“蝶后”张雨霏当之无愧的占领榜首,不过这清一色的蓝色条,让人不得不感叹中国游泳队的强大。除此之外,田径和乒乓球也是很容易获得多枚金牌的项目。

最后的最后,我们用词云图来看看中国运动员的热门情况(获得金牌数越高越热门),你第一眼看见了谁的名字?欢迎在评论区留言。

image.png

g2({
  type: "wordCloud",
  padding: 0,
  data: data.filter((d) => d.noc === "CHN"),
  encode: {
    text: "name",
    value: "gold",
    color: "sport"
  },
  legend: { color: false },
  layout: { fontSize: [5, 50] },
  style: { textBaseline: "middle" }
})

洞察

到这里我们所有的分析任务都已经完成了,接下来我们就来总结一下我们获得洞察。

第一,中国队很厉害,但我们也应该为大部分未获奖参赛国家喝彩。 可以发现中国队不仅仅是获得奖牌最多的国家,同时也是获得奖牌效率最高的国家,而其中的游泳、龙舟、射击、田径和赛艇运动员的表现尤为的亮眼。同时我们也可以发现大部分国家都有很多项目没有参加,参加的也都大部分没有获得奖牌。不过还是得为这些国家运动员致以崇高的敬意,因为敢于拼搏才是奥林匹克运动会所倡导的精神。

第二,00后成为了参赛的主力军,10后也开始崭露头角。 大部分的参赛和获奖队员都是在2000到2005年这个区间出生的。这意味着为国体育争光得重担,也渐渐从90后移交到了这些20岁左右的千禧年“小孩”的手里。让人感到惊喜的是,也有不少10后的运动员出现在了赛场上并且获得奖牌,这也许就是体育精神的传承吧。

第三,年龄会影响成绩,但是“高龄运动员”也有春天。 通过分析发现,获得金牌的运动员大部分都在23岁左右,而26岁到31岁是获得银牌和铜牌的最佳年龄段,所以获得金牌和出名一样,得“趁早”。但是事情总有转机。我们发现一些大于40岁的高龄运动员也很多了不错的成绩,其中不乏金牌的获得者,当然这部分大多都是棋牌类比赛的运动员。不管怎么说,这确实也体现了亚运会对年龄的包容性,每运动员都有属于自己的获得奖牌的“时区”。

第四,大部分运动男女比例均衡,少部分失平衡。 在多数项目里面,男性运动员都比女性运动员要稍微多一点点。当然,也有个别项目(棒球、垒球、花样游泳等)因为项目性质出现运动员性别一边倒的情况。不过,一个不能忽视的事实就是:参加电子竞技的女性运动员凤毛麟角。

第五,不同运动的身高分布不同,高身高运动员获得奖牌也许更难。 和我们日常的认知一样,排球和篮球这样“巨人运动”的运动员往往具有较高的身高,而滑板运动员身高相对较矮是因为他们的年龄都相对较小。同时高尔夫球的运动员的身高差异是最小的。在分析身高和获奖情况之间的关系的时候,我们也发现没有得奖牌的运动员身高普遍偏高,也许身高越高越不容易获得奖牌?

第六,不能被忽视的中国女性力量。 这是可能这次分析最大的收获。中国大部分参赛女性运动员都获得了奖牌,这其中大部分还是金牌,相比之下参赛男性运动员几乎有一半都没有获得奖牌。另一方面,女性获奖的运动员的年龄覆盖面也更广,尤其是金牌,最小13岁,最大59岁。当然最后,我们国家金牌榜的榜首也是一位女性:游泳运动员张雨霏。这不得不让人想起了女篮决赛赛场上,观众高举的那条横幅:“无畏金兰”。

结语

这就是本篇文章的全部内容了,欢迎大家和我们讨论本次得到的结论。当然,如果大家还有更多的问题,也不用着急,毕竟工具思路都在这里了,还等什么?快快行动起来吧!

如果觉得本文还不错的,欢迎去给下面的工具和仓库点赞 🌟🌟🌟,你们的支持是我们最大的动力!