简体   繁体   English

计算同现的更有效方法

[英]More efficient way to compute cooccurrence

I want to visualise a network of relationships between people. 我想形象化人与人之间的关系网络。

My data looks like this : 我的数据如下所示:

let networkData = [
    ["John","Dylan","Brian"],
    ["Dylan","Brian"],
];

And I want an output like this : 我想要这样的输出:

let networkMatrix.links = [
    {source: "John",  target: "Dylan", weight: 1},
    {source: "John",  target: "Brian", weight: 1},
    {source: "Brian", target: "Dylan", weight: 2}
];

John and Brian share one group so their weight is 1. The same is true for John and Dylan. 约翰和布莱恩共享一组,所以他们的权重为1。约翰和迪伦也是如此。 As Dylan and Brian share in two groups, their relationship gets a weight of 2. 由于Dylan和Brian分成两组,他们的关系权重为2。

Now here is where I think I need help. 现在,这里是我认为需要帮助的地方。 My way of doing that was to go through each line of networkData , then through each element of the array. 我这样做的方法是遍历networkData每一行,然后遍历数组的每个元素。 And for each element, go through all the elements that come after, and increment their score in networkMatrix . 对于每个元素,请遍历之后的所有元素,并在networkMatrix增加其得分。 Here is my code. 这是我的代码。

var i = 0, j = 0;
networkData.map(function(d) {
    d.forEach(function(val, ind, tab) {
        for (let k = ind + 1; k < tab.length; k++) {
            while ((i = networkMatrix.person1.indexOf(val, i + 1)) != -1) {
                while ((j = networkMatrix.person2.indexOf(tab[k], j + 1)) != -1) {
                    if (i === j) {
                        networkMatrix.score[i]++;
                    }
                }
            }
        }
    })
});

Here is a jsfiddle : https://jsfiddle.net/0t81jg3b/2/ 这是一个jsfiddle: https ://jsfiddle.net/0t81jg3b/2/

As you can see it doesn't even work on jsfiddle. 如您所见,它甚至在jsfiddle上也不起作用。 But it works more or less on my computer, I don't know why : 但是它或多或少在我的计算机上工作,我不知道为什么:

在此处输入图片说明

If feel like this is getting waaaaay too complicated for such a simple task, could someone give me some indications on how to get out of this mess? 如果对于这样一个简单的任务来说,这样变得太复杂了,有人可以给我一些如何摆脱困境的指示吗?

You could do it as follows: 您可以按照以下步骤进行操作:

  • Only consider name pairs where the source is alphabetically less than the target 仅考虑源对字母顺序小于目标对的名称对
  • Build a map keyed by source, and for each a nested map keyed by target, and assign a counter to those nested keys. 构建一个以源为键的映射,并为每个目标以键映射的嵌套映射,并为这些嵌套键分配一个计数器。 You could use an ES6 Map for that, or else plain object 您可以为此使用ES6 Map ,否则可以使用普通对象

 const groupes = [ ["John", "Dylan", "Brian"], ["Dylan", "Brian"], ["John", "Kate"] ], // Get unique list of names names = [...new Set([].concat(...groupes))], // Create a 2D-map with a counter set to zero map = new Map(names.map(name => [name, new Map(names.map(name2 => [name2, 0]))])), result = []; // Count the pairs for (const groupe of groupes) { for (const source of groupe) { const targetMap = map.get(source); for (const target of groupe) { if (source < target) targetMap.set(target, targetMap.get(target)+1); } } } // Convert nested maps to result structure for (const [source, targetMap] of map.entries()) { for (const [target, weight] of targetMap.entries()) { if (weight) result.push({source, target, weight}); } } console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM