首页 > 解决方案 > 按管道字符拆分 CSV 列并计算唯一值

问题描述

我有一个包含管道分隔值列的 csv 文件。例子:

一个
1 苹果|熊
2 苹果|汽车
3 狗|猫|鸸鹋
4 熊|鸸鹋

对于 B 列,我需要通过管道将其拆分并计算每个唯一值。输出将如下所示:

数数
苹果 2
2
2
1
1
1

我正在尝试学习 D3.js,但我对 d3 或 javascript 的经验还不够丰富。所以,现在,我有以下内容:

var b_counts = d3.nest()
        .key(function(d) { return d.B })
        .rollup(function(item) {
            return item.length;
        })
        .entries(data)
        .map(function(group) {
            return {
                B: group.key,
                Count: group.value
            }
        });

哪个非常好,可以让我计算 B 列中每个唯一项目的数量:

数数
苹果|熊 1
苹果|汽车 1
狗|猫|鸸鹋 1
熊|鸸鹋 1

但我真正想要的是 B 中每个唯一值的计数。

在带有熊猫的python中,我会做

df.B.split("|").explode().value_counts().rename_axis("B").reset_index(name="Count")

但是 javascript/d3 对我来说又是陌生的,谷歌并没有完全给我解决方案,我可以拼凑起来让它做我需要的事情。

帮助?

标签: javascriptd3.js

解决方案


这是执行此操作的一种方法。首先,我们得到一个包含 B 列中所有单个值的数组。然后我们使用d3.rollup来统计每个值出现的次数。

const data = [
  { A: 1, B: 'Apple|Bear' },
  { A: 2, B: 'Apple|Car' },
  { A: 3, B: 'Dog|Cat|Emu' },
  { A: 4, B: 'Bear|Emu' },
];

// split each B attribute by the pipe
// flatten the 2D array into a 1D array
const values = data.map(d => d.B.split('|')).flat();

// count the number of times each value appears
const counts = d3.rollup(
  values,
  group => group.length,
  d => d
);

这会产生一个地图。如果您想要一个对象数组,那么您可以这样做

// count the number of times each value appears
// rollups returns an array of key-value pairs
const counts = d3.rollups(
  values,
  group => group.length,
  d => d
)
  // convert the array of arrays into an array of objects
  .map(([B, Count]) => ({B, Count}))

推荐阅读