Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/463.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带标签和加权边的Javascript网络_Javascript_Graph_Visualization - Fatal编程技术网

带标签和加权边的Javascript网络

带标签和加权边的Javascript网络,javascript,graph,visualization,Javascript,Graph,Visualization,我已经搜索了很长一段时间,但我找不到一个简单的JS库来创建一个网络,其中: 节点具有标签 边缘厚度与重量成正比 能够分散节点,使其不会变得混乱 我在bl.ocks.org上找到了一个适合我需要的脚本,但是当我使用很多节点时,它变得非常混乱: 我使用它作为输入: target,source,weight woooooow,notgood,70.0 woooooow,gainzz,32.004950495049506 woooooow,test,33.86138613861386 wooooo

我已经搜索了很长一段时间,但我找不到一个简单的JS库来创建一个网络,其中:

  • 节点具有标签
  • 边缘厚度与重量成正比
  • 能够分散节点,使其不会变得混乱
我在bl.ocks.org上找到了一个适合我需要的脚本,但是当我使用很多节点时,它变得非常混乱:

我使用它作为输入:

target,source,weight
woooooow,notgood,70.0
woooooow,gainzz,32.004950495049506
woooooow,test,33.86138613861386
woooooow,peanutss,20.866336633663366
nicecode,woooooow,22.103960396039604
woooooow,oreo,20.742574257425744
bread,woooooow,37.945544554455445
jam,nutella,20.123762376237625
bread,nutsarelol,20.866336633663366
etc
问题
我可以使用哪种代码/库来创建一个类似于上面的图但节点分布更广的图

JS代码

/*
Author: Corneliu S. (github.com/upphiminn)

This is a javascript implementation of the Louvain
community detection algorithm (http://arxiv.org/abs/0803.0476)
Based on https://bitbucket.org/taynaud/python-louvain/overview

*/
(function(){
    jLouvain = function(){
        //Constants
        var __PASS_MAX = -1
        var __MIN    = 0.0000001

        //Local vars
        var original_graph_nodes;
        var original_graph_edges;
        var original_graph = {};
        var partition_init;

        //Helpers
        function make_set(array){
            var set = {};
            array.forEach(function(d,i){
                set[d] = true;
            });
            return Object.keys(set);
        };

        function obj_values(obj){
             var vals = [];
             for( var key in obj ) {
                 if ( obj.hasOwnProperty(key) ) {
                     vals.push(obj[key]);
                 }
             }
             return vals;
        };

        function get_degree_for_node(graph, node){
            var neighbours = graph._assoc_mat[node] ? Object.keys(graph._assoc_mat[node]) : [];
            var weight = 0;
            neighbours.forEach(function(neighbour,i){
                var value = graph._assoc_mat[node][neighbour] || 1;
                if(node == neighbour)
                    value *= 2;
                weight += value;
            });
            return weight;
        };

        function get_neighbours_of_node(graph, node){
            if(typeof graph._assoc_mat[node] == 'undefined')
                return [];

            var neighbours = Object.keys(graph._assoc_mat[node]);
            return neighbours;
        }

        function get_edge_weight(graph, node1, node2){
            return graph._assoc_mat[node1] ? graph._assoc_mat[node1][node2] : undefined;
        }

        function get_graph_size(graph){
            var size = 0;
            graph.edges.forEach(function(edge){
                size += edge.weight;
            });
            return size;
        }

        function add_edge_to_graph(graph, edge){
            update_assoc_mat(graph, edge);

            var edge_index = graph.edges.map(function(d){
                return d.source+'_'+d.target;
            }).indexOf(edge.source+'_'+edge.target);

            if(edge_index != -1)
                graph.edges[edge_index].weight = edge.weight;
            else
                graph.edges.push(edge);
        }

        function make_assoc_mat(edge_list){
            var mat = {};
            edge_list.forEach(function(edge, i){
                mat[edge.source] = mat[edge.source] || {};
                mat[edge.source][edge.target] = edge.weight;
                mat[edge.target] = mat[edge.target] || {};
                mat[edge.target][edge.source] = edge.weight;
            });

            return mat;
        }

        function update_assoc_mat(graph, edge){
            graph._assoc_mat[edge.source] = graph._assoc_mat[edge.source] || {};
            graph._assoc_mat[edge.source][edge.target] = edge.weight;
            graph._assoc_mat[edge.target] = graph._assoc_mat[edge.target] || {};
            graph._assoc_mat[edge.target][edge.source] = edge.weight;
        }

        function clone(obj){
            if(obj == null || typeof(obj) != 'object')
                return obj;

            var temp = obj.constructor();

            for(var key in obj)
                temp[key] = clone(obj[key]);
            return temp;
        }

        //Core-Algorithm Related
        function init_status(graph, status, part){
            status['nodes_to_com'] = {};
            status['total_weight'] = 0;
            status['internals'] = {};
            status['degrees'] = {};
            status['gdegrees'] = {};
            status['loops'] = {};
            status['total_weight'] = get_graph_size(graph);

            if(typeof part == 'undefined'){
                graph.nodes.forEach(function(node,i){
                    status.nodes_to_com[node] = i;
                    var deg = get_degree_for_node(graph, node);
                    if (deg < 0)
                        throw 'Bad graph type, use positive weights!';
                    status.degrees[i] = deg;
                    status.gdegrees[node] = deg;
                    status.loops[node] = get_edge_weight(graph, node, node) || 0;
                    status.internals[i] = status.loops[node];
                });
            }else{
                graph.nodes.forEach(function(node,i){
                    var com = part[node];
                    status.nodes_to_com[node] = com;
                    var deg = get_degree_for_node(graph, node);
                    status.degrees[com] = (status.degrees[com] || 0) + deg;
                    status.gdegrees[node] = deg;
                    var inc = 0.0;

                    var neighbours  = get_neighbours_of_node(graph, node);
                    neighbours.forEach(function(neighbour, i){
                        var weight = graph._assoc_mat[node][neighbour];
                        if (weight <= 0){
                            throw "Bad graph type, use positive weights";
                        }

                        if(part[neighbour] == com){
                            if (neighbour == node){
                                inc += weight;
                            }else{
                                inc += weight/2.0;
                            }
                        }
                    });
                    status.internals[com] = (status.internals[com] || 0) + inc;
                });
            }
        }

        function __modularity(status){
            var links = status.total_weight;
            var result = 0.0;
            var communities = make_set(obj_values(status.nodes_to_com));

            communities.forEach(function(com,i){
                var in_degree = status.internals[com] || 0 ;
                var degree = status.degrees[com] || 0 ;
                if(links > 0){
                    result = result + in_degree / links - Math.pow((degree / (2.0*links)), 2);
                }
            });
            return result;
        }

        function __neighcom(node, graph, status){
            // compute the communities in the neighb. of the node, with the graph given by
            // node_to_com

            var weights = {};
            var neighboorhood = get_neighbours_of_node(graph, node);//make iterable;

            neighboorhood.forEach(function(neighbour, i){
                if(neighbour != node){
                    var weight = graph._assoc_mat[node][neighbour] || 1; 
                    var neighbourcom = status.nodes_to_com[neighbour];
                    weights[neighbourcom] = (weights[neighbourcom] || 0) + weight;
                }   
            });

            return weights;
        }

        function __insert(node, com, weight, status){
            //insert node into com and modify status
            status.nodes_to_com[node] = +com;
            status.degrees[com] = (status.degrees[com] || 0) + (status.gdegrees[node]||0);
            status.internals[com] = (status.internals[com] || 0) + weight + (status.loops[node]||0);
        }

        function __remove(node, com, weight, status){
            //remove node from com and modify status
            status.degrees[com] = ((status.degrees[com] || 0) - (status.gdegrees[node] || 0));
            status.internals[com] = ((status.internals[com] || 0) - weight -(status.loops[node] ||0));
            status.nodes_to_com[node] = -1;
        }

        function __renumber(dict){
            var count = 0;
            var ret = clone(dict); //deep copy :)
            var new_values = {};
            var dict_keys = Object.keys(dict);
            dict_keys.forEach(function(key){
                var value = dict[key];
                var new_value =  typeof new_values[value] =='undefined' ? -1 : new_values[value];
                if(new_value == -1){
                    new_values[value] = count;
                    new_value = count;
                    count = count + 1;
                }
                ret[key] = new_value;
            });
            return ret;
        }

        function __one_level(graph, status){
            //Compute one level of the Communities Dendogram.
            var modif = true,
                nb_pass_done = 0,
                cur_mod = __modularity(status),
                new_mod = cur_mod;

            while (modif && nb_pass_done != __PASS_MAX){
                cur_mod = new_mod;
                modif = false;
                nb_pass_done += 1

                graph.nodes.forEach(function(node,i){
                    var com_node = status.nodes_to_com[node];
                    var degc_totw = (status.gdegrees[node] || 0) / (status.total_weight * 2.0);
                    var neigh_communities = __neighcom(node, graph, status);
                    __remove(node, com_node, (neigh_communities[com_node] || 0.0), status);
                    var best_com = com_node;
                    var best_increase = 0;
                    var neigh_communities_entries = Object.keys(neigh_communities);//make iterable;

                    neigh_communities_entries.forEach(function(com,i){
                        var incr = neigh_communities[com] - (status.degrees[com] || 0.0) * degc_totw;
                        if (incr > best_increase){
                            best_increase = incr;
                            best_com = com;
                        }
                    });

                    __insert(node, best_com, neigh_communities[best_com] || 0, status);

                    if(best_com != com_node)
                        modif = true;
                });
                new_mod = __modularity(status);
                if(new_mod - cur_mod < __MIN)
                    break;
            }
        }

        function induced_graph(partition, graph){
            var ret = {nodes:[], edges:[], _assoc_mat: {}};
            var w_prec, weight;
            //add nodes from partition values
            var partition_values = obj_values(partition);
            ret.nodes = ret.nodes.concat(make_set(partition_values)); //make set
            graph.edges.forEach(function(edge,i){
                weight = edge.weight || 1;
                var com1 = partition[edge.source];
                var com2 = partition[edge.target];
                w_prec = (get_edge_weight(ret, com1, com2) || 0); 
                var new_weight = (w_prec + weight);
                add_edge_to_graph(ret, {'source': com1, 'target': com2, 'weight': new_weight});
            });
            return ret;
        }

        function partition_at_level(dendogram, level){
            var partition = clone(dendogram[0]);
            for(var i = 1; i < level + 1; i++ )
                Object.keys(partition).forEach(function(key,j){
                    var node = key;
                    var com  = partition[key];
                    partition[node] = dendogram[i][com];
                });
            return partition;
        }


        function generate_dendogram(graph, part_init){

            if(graph.edges.length == 0){
                var part = {};
                graph.nodes.forEach(function(node,i){
                    part[node] = node;
                });
                return part;
            }
            var status = {};

            init_status(original_graph, status, part_init);
            var mod = __modularity(status);
            var status_list = [];
            __one_level(original_graph, status);
            var new_mod = __modularity(status);
            var partition = __renumber(status.nodes_to_com);
            status_list.push(partition);
            mod = new_mod;
            var current_graph = induced_graph(partition, original_graph);
            init_status(current_graph, status);

            while (true){
                __one_level(current_graph, status);
                new_mod = __modularity(status);
                if(new_mod - mod < __MIN)
                    break;

                partition = __renumber(status.nodes_to_com);
                status_list.push(partition); 

                mod = new_mod;
                current_graph = induced_graph(partition, current_graph);
                init_status(current_graph, status);
            }

            return status_list; 
        }

        var core = function(){
            var status = {};
            var dendogram = generate_dendogram(original_graph, partition_init);
            return partition_at_level(dendogram, dendogram.length - 1);
        };

        core.nodes = function(nds){
            if(arguments.length > 0){
                original_graph_nodes = nds;
            }
            return core;
        };

        core.edges = function(edgs){
            if(typeof original_graph_nodes == 'undefined')
                throw 'Please provide the graph nodes first!';

            if(arguments.length > 0){
                original_graph_edges = edgs;
                var assoc_mat = make_assoc_mat(edgs);
                original_graph = { 'nodes': original_graph_nodes,
                                   'edges': original_graph_edges,
                                   '_assoc_mat': assoc_mat };
            }
            return core;

        };

        core.partition_init = function(prttn){
            if(arguments.length > 0){
                partition_init = prttn;
            }
            return core;
        };

        return core;
    }
})();
/*
作者:Corneliu S.(github.com/upphiminn)
这是Louvain的javascript实现
社区检测算法(http://arxiv.org/abs/0803.0476)
基于https://bitbucket.org/taynaud/python-louvain/overview
*/
(功能(){
jLouvain=函数(){
//常数
var uu PASS_MAX=-1
var\uu MIN=0.0000001
//局部变量
var原图节点;
var原图边;
var原_图={};
var-partition_init;
//助手
函数生成集合(数组){
变量集={};
forEach(函数(d,i){
设置[d]=真;
});
返回Object.key(set);
};
函数obj_值(obj){
var VAL=[];
for(obj中的var键){
if(对象hasOwnProperty(键)){
VAL.push(对象[键]);
}
}
返回VAL;
};
函数获取节点的度(图,节点){
var neights=graph.\u assoc\u mat[node]?Object.keys(graph.\u assoc\u mat[node]):[];
变量权重=0;
forEach(函数(邻居,i){
var值=图形。_assoc_mat[节点][邻居]| 1;
if(节点==邻居)
数值*=2;
重量+=价值;
});
返回重量;
};
函数get\u node的邻居(图,节点){
if(图形类型。\u assoc\u mat[node]=“未定义”)
返回[];
var neights=Object.keys(图.assoc\u mat[node]);
返回邻居;
}
函数获取边权重(图、节点1、节点2){
返回图._assoc_mat[node1]?图._assoc_mat[node1][node2]:未定义;
}
函数获取图大小(图){
变量大小=0;
graph.edges.forEach(函数(边){
尺寸+=边缘重量;
});
返回大小;
}
函数将边添加到图(图,边){
更新相关材料(图形、边缘);
var edge_index=graph.edges.map(函数(d){
返回d.source+“”+d.target;
}).indexOf(edge.source+“”“+”edge.target);
如果(边索引!=-1)
graph.edges[edge_index].weight=edge.weight;
其他的
图.边.推(边);
}
功能制作相关材料(边缘列表){
var mat={};
edge_list.forEach(函数(edge,i){
mat[edge.source]=mat[edge.source]|{};
mat[edge.source][edge.target]=edge.weight;
mat[edge.target]=mat[edge.target]|{};
mat[edge.target][edge.source]=edge.weight;
});
返回垫;
}
功能更新\u关联\u材料(图形、边缘){
图._assoc_mat[edge.source]=图._assoc_mat[edge.source]|{};
图._assoc_mat[edge.source][edge.target]=edge.weight;
graph._assoc_mat[edge.target]=graph._assoc_mat[edge.target]|{};
图._assoc_mat[edge.target][edge.source]=edge.weight;
}
功能克隆(obj){
if(obj==null | | typeof(obj)!='object')
返回obj;
var temp=obj.constructor();
for(obj中的var键)
temp[key]=克隆(obj[key]);
返回温度;
}
//核心算法相关
函数初始状态(图形、状态、零件){
状态['nodes_to_com']={};
状态['total_weight']=0;
状态['internals']={};
状态['degrees']={};
状态['gdegrees']={};
状态['loops']={};
状态['total_weight']=获取图形大小(图形);
如果(零件类型==‘未定义’){
graph.nodes.forEach(函数(node,i){
status.nodes_to_com[node]=i;
var deg=获取节点的度(图,节点);
如果(度<0)
抛出“错误的图形类型,使用正权重!”;
状态。度[i]=度;
状态.gdegrees[节点]=度;
status.loops[node]=get_edge_weight(图形、节点、节点)| 0;
status.internal[i]=status.loops[node];
});
}否则{
graph.nodes.forEach(函数(node,i){
var com=部件[节点];
status.nodes_to_com[node]=com;
var deg=获取节点的度(图,节点);
status.degrees[com]=(status.degrees[com]| | 0)+deg;
状态.gdegrees[节点]=度;
var inc=0.0;
var Neights=获取节点(图,节点)的\u Neights\u;
forEach(函数(邻居,i){
变量权重=图。关联矩阵[节点][邻居];
如果(重量0){
结果=结果+学位/链接-数学能力((学位/(2.0*链接)),2);
}
});
返回结果;
}
函数_neighcom(节点、图形、状态){
//计算社区