d3.groups 通过给定键数组的多个键

d3.groups by multiple keys given array of of keys

在此处查看工作 fiddle:https://jsfiddle.net/0qgtbk9r/9/

假设我有一个数据对象数组,并且用户提供了多个键作为分组依据。我想利用 d3.groups 按这些键进行分组。

对于我的 fiddle 示例,我知道我可以“手动”链接这两个键以获得我想要的:

var gps = d3.groups(objs, d => d.Eye, d => d.Sex)

但我很难编码 d.Eye / d.Sex...

所以我的问题是,如果我提供一个键数组来按...进行分组,如何获得相同的结果,如下所示:

var gb_keys = ['Eye','Sex']
var gps = d3.groups(obj,d=>gb_key.map(x=>d.x)//Doesn't work but just a random idea/thought

这是 similar/almost 与 的重复,但问题已经很老了,我想知道现在是否存在基于 d3 的解决方案。 ?

d3.flatGroup and were introduced in v7 which address the issue of the nested structure tackled in the 你引用了。

对于 user-defined 键数组,您可以在 d3.flatGroup(和 d3.groups 等)中使用此方法:

var fields = ['Sex','Eye']
var gps = d3.flatGroup(
  objs,
  ...fields.map(k => d => d[k]) // instead of d => d.Sex and d => d.Eye etc
)

工作示例:

var fields = ['Sex','Eye']
var gps = d3.flatGroup(
  objs,
  ...fields.map(k => d => d[k])
)
console.log(gps)
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/d3.min.js"></script>
<script>
const ds = `Sex,Age,Eye,Height
M,43,blue,190
M,31,brown,200
M,50,blue,175
M,58,blue,210
M,26,blue,181
M,22,brown,202
M,59,green,189
M,52,brown,198
M,26,green,203
M,54,brown,201
M,29,brown,202
M,44,brown,178
F,58,brown,135
F,56,green,169
F,41,brown,155
F,23,brown,131
F,34,green,151
F,43,green,155
F,39,brown,176
F,42,blue,174
F,38,green,176
F,31,green,149
F,41,green,161
F,37,blue,178
F,35,brown,157
F,33,brown,150
F,41,blue,138
F,33,blue,147
F,21,green,144
F,47,brown,176
F,22,brown,169
F,22,brown,164
F,53,blue,144`
var objs = d3.csvParse(ds)
</script>

要满足对象数组而不是数组数组的要求,您可以这样做:

var fields = ['Sex','Eye']
var gps = d3.flatGroup(
  objs,
  ...fields.map(k => d => d[k])
);

var fields2 = fields.concat('values');
var gps2 = gps.map(
  gp => Object.fromEntries(
    fields2.map((_, i) => [fields2[i], gp[i]])
  )
);

工作示例:

var fields = ['Sex','Eye']
var gps = d3.flatGroup(
  objs,
  ...fields.map(k => d => d[k])
);

var fields2 = fields.concat('values');
var gps2 = gps.map(
  gp => Object.fromEntries(
    fields2.map((_, i) => [fields2[i], gp[i]])
  )
);
console.log(gps2);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/d3.min.js"></script>
<script>
const ds = `Sex,Age,Eye,Height
M,43,blue,190
M,31,brown,200
M,50,blue,175
M,58,blue,210
M,26,blue,181
M,22,brown,202
M,59,green,189
M,52,brown,198
M,26,green,203
M,54,brown,201
M,29,brown,202
M,44,brown,178
F,58,brown,135
F,56,green,169
F,41,brown,155
F,23,brown,131
F,34,green,151
F,43,green,155
F,39,brown,176
F,42,blue,174
F,38,green,176
F,31,green,149
F,41,green,161
F,37,blue,178
F,35,brown,157
F,33,brown,150
F,41,blue,138
F,33,blue,147
F,21,green,144
F,47,brown,176
F,22,brown,169
F,22,brown,164
F,53,blue,144`
var objs = d3.csvParse(ds)
</script>