Echarts5.* 关系图谱(relation graph)如何以某节点为圆心,子节点环绕其排列布局?

20 篇文章 1 订阅
4 篇文章 0 订阅

前言

Echarts5.*中,关系图谱(relation graph)中的每个节点必须给xy坐标,才会显示在画布上,在前一篇文章里我采用的方法是,随机生成坐标点,可这样会导致节点布局混乱,无法理清各个节点之间的关系。希望能做到如下的优化:

  1. 选取某个节点作为中心点(取画布中心值)
  2. 特定类型的子节点,会环绕在它父类节点周围显示

后期的效果如下图所示:

选取画布中心点

核心代码如下所示:

<template>
    <div ref="main" id="graph"></div>
</template>

<script>
import * as echarts from 'echarts'
export default {
    name: "graph",
    methods: {
    	getCenterPos() {
            const x = (this.$refs.main.clientWidth - 40) * 0.5
            const y = (this.$refs.main.clientHeight - 200) * 0.5
            return {
                x,
                y
            }
        }
    }
}
</script>

以父节点为圆心,将子节点等分并返回坐标信息

该方法如下所示:

<template>
    <div ref="main" id="graph"></div>
</template>

<script>
import * as echarts from 'echarts'
export default {
    name: "graph",
    methods: {
    	/**
    	 * @param {Object} {x,y} 圆心坐标
    	 * @param {Number} index 索引值,即该子节点在所有同类型子节点中的位置索引(数组索引位置)
    	 * @params {Number} nodesLen 子节点个数
    	 * @params {Number} radius 半径
    	 */
    	circledNodesPosition({x,y}, index, nodesLen, radius = 20) {
            const avd = 360 / nodesLen;
            const ahd = avd * Math.PI / 180
            return {
                x: Math.sin((ahd*index))*radius + x,
                y: Math.cos((ahd*index))*radius + y
            }
        },
    }
</script>

360 / nodesLen,即每个子节点对应的角度
avd * Math.PI / 180, 即每个子节点对应的弧度

Math.sin((ahd*index))*radius,得到该子节点与圆中心的x方向偏移值,若需知道该子节点的x坐标信息,则需加上圆心的x

将所有节点按类型分组

核心代码如下所示:

initGraph() {
	const buildingNode = []
	
	const componentNodes = []
	
	const personNodes = []
	let personCenterPos = null
	
	const companyNodes = []
	let companyCenterPos = null
	
	const roomNodes = []
	let roomCenterPos = null
	
	var center = this.getCenterPos()
	graph.nodes.forEach(a => {
		const {labels, id, properties} = a
		const type = labels[0]
		if (type === 'Building') {
		    buildingNode.push({
		        ...param,
		        x: center.x,
		        y: center.y
		    })
		} else if(type === 'Component') {
		    componentNodes.push({
		        ...param
		    })
		} else if (type === 'Person') {
		    personNodes.push({
		        ...param
		    })
		} else if (type === 'Company') {
		    companyNodes.push({
		        ...param
		    })
		} else if (type === 'Room') {
		    roomNodes.push({
		        ...param
		    })
		}
	})
	componentNodes.forEach((a,index) => {
	    var pos = this.circledNodesPosition(center, index, componentNodes.length)
	    a.x = pos.x
	    a.y = pos.y
	    const cType = a.properties.find(a=> a.key === 'component_name').value
	    if (cType === '人') {
	        personCenterPos = {
	            x: a.x,
	            y: a.y
	        }
	    } else if (cType === '企业') {
	        companyCenterPos = {
	            x: a.x,
	            y: a.y
	        }
	    } else if (cType === '房间') {
	        roomCenterPos = {
	            x: a.x,
	            y: a.y
	        }
	    }
	})
	
	const generateNodesPos = (nodes, centerPos, nodesLen) => {
        nodes.forEach((a,index) => {
		    var pos = this.circledNodesPosition(centerPos, index, nodesLen, 5)
		    a.x = pos.x
		    a.y = pos.y
		})
	}
	
	generateNodesPos(personNodes, personCenterPos, personNodes.length)
	generateNodesPos(companyNodes, companyCenterPos, companyNodes.length)
	generateNodesPos(roomNodes, roomCenterPos, roomNodes.length)
	
	const nodes = [
	    ...buildingNode,
	    ...componentNodes,
	    ...personNodes,
	    ...companyNodes,
	    ...roomNodes
	]
	
	var option = {
	    tooltip: {},
	    animationDuration: 1500,
	    animationEasingUpdate: 'quinticInOut',
	    hoverAnimation:false,
	    series: [
	        {
	            // name: '孪生',
	            type: 'graph',
	            layout: 'none',
	            circular:{rotateLabel:true},
	            animation: false,
	            data: nodes
	            ...
	        }
	    ]
	} 
	myChart.setOption(option);
}

在上面代码中,我先从所有节点中过滤出componentNodes,因为它是类型聚合点,再根据不同类型,将子节点划分到对应数组中,找出同类型中的圆中心点,遍历同类型子节点,生成各个子节点的x,y坐标信息即可

​​

### 回答1: 要统计py2neo知识图谱中每个节点及其关系的频次,需要使用Cypher查询语言。以下是一个示例查询语句,可以帮助您获取每个节点及其关系的频次: ``` MATCH (n)-[r]->() RETURN labels(n) AS node_type, type(r) AS relationship_type, count(*) AS frequency ORDER BY frequency DESC ``` 上述查询语句将返回一个结果集,其中包含每个节点的标签、每个关系的类型以及对应的频次。请注意,这个查询语句假定每个节点都有一个标签(即类别),如果您的中存在没有标签的节点,则需要对查询语句进行相应的修改。 此外,如果您想进一步筛选结果,可以添加WHERE子句来限定查询范围,例如: ``` MATCH (n)-[r]->() WHERE labels(n) = 'Person' RETURN labels(n) AS node_type, type(r) AS relationship_type, count(*) AS frequency ORDER BY frequency DESC ``` 上述查询语句将只返回标签为“Person”的节点及其关系的频次。 ### 回答2: Py2neo是Python中的一个库,用于操作Neo4j数据库。在知识图谱中,每个节点都代表一个实体,而这些实体之间的关系可以通过边来表示。每个节点关系都可以有自己的属性,例如类别、频次等。要计算每个节点关系的频次,首先需要对图谱中的节点关系进行遍历。 首先,我们可以通过Py2neo库连接到Neo4j数据库,并查询所有的节点关系。然后,我们可以使用Cypher查询语言对图谱进行遍历,计算每个节点关系的频次。 下面是一个示例代码: ```python from py2neo import Graph, NodeMatcher # 连接到Neo4j数据库 graph = Graph("bolt://localhost:7687", auth=("username", "password")) # 创建节点匹配器 matcher = NodeMatcher(graph) # 存储节点关系频次的字典 relation_freq = {} # 查询所有节点关系 nodes = matcher.match() # 查询所有节点 relationships = graph.relationships # 查询所有关系 # 遍历所有节点 for node in nodes: node_type = node.get("type") # 获取节点类别 # 初始化节点类别的关系频次为0 if node_type not in relation_freq: relation_freq[node_type] = {} # 遍历所有关系 for relationship in relationships: start_node = relationship.start_node # 获取关系的开始节点 # 如果开始节点类型等于当前节点类型 if start_node.get("type") == node_type: rel_type = relationship.type() # 获取关系的类别 # 更新该节点类别的关系频次 if rel_type not in relation_freq[node_type]: relation_freq[node_type][rel_type] = 1 else: relation_freq[node_type][rel_type] += 1 # 打印节点类别的关系频次 for node_type, rel_freq in relation_freq.items(): print("节点类别: {}".format(node_type)) for rel_type, freq in rel_freq.items(): print("关系类别: {}, 频次: {}".format(rel_type, freq)) print("\n") ``` 以上代码中,我们首先连接到Neo4j数据库,然后创建一个节点匹配器,用于查询所有节点。通过遍历所有节点关系,我们可以获取节点的类别和关系的类别,并计算每个节点关系的频次。最后,我们打印出节点类别的关系频次。 请注意,此代码仅做示例用途,实际情况可能会因数据库结构和数据模型的不同而有所差异。请根据实际需求进行适当的修改。 ### 回答3: py2neo是一个用于构建和操作Neo4j数据库的Python库。知识图谱是一种用于表示和组织知识的状数据结构。在py2neo中,每个节点都可以有一个类别标签,用于指定节点的类型。节点之间的关系也可以被分类别标记,以指定不同关系之间的语义含义。 通过py2neo可以方便地计算每个节点关系频次。以下是一个简单的示例代码,用于统计节点关系的频次: ```python from py2neo import Graph # 连接到Neo4j数据库 graph = Graph("<你的Neo4j数据库连接地址>") # 查询节点的类别和关系的分类别频次 node_freq = graph.run("MATCH (n) RETURN DISTINCT labels(n) AS label, count(*) AS freq") rel_freq = graph.run("MATCH ()-[r]->() RETURN DISTINCT type(r) AS type, count(*) AS freq") # 打印节点的类别和关系的分类别频次 print("节点类别频次:") for record in node_freq: node_label = record["label"] freq = record["freq"] print(f"{node_label}: {freq}") print("\n关系分类别频次:") for record in rel_freq: rel_type = record["type"] freq = record["freq"] print(f"{rel_type}: {freq}") ``` 该代码会查询数据库中所有节点的类别和关系的分类别,并计算他们的频次。最后,会打印出节点类别频次和关系分类别频次。 需要注意的是,上述代码仅提供了一个简单的示例,具体的查询语句和统计方法可以根据实际需求进行修改和扩展。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值