尝试将networkx实现为graphicsscene

时间:2017-02-18 16:25:51

标签: pandas pyqt4 networkx qgraphicsview qgraphicsscene

-------- companytrades.csv --------

date,Company1,Company2
1/2/2017,1001,1111
1/3/2017,1001,1100
1/4/2017,1111,1001
1/5/2017,1100,1001
1/6/2017,1011,1001
1/7/2017,1001,1111
1/8/2017,1111,1100
1/9/2017,1100,1011

我发现了一个将一组实现networkx的类放入graphicsscene GraphNetworkX.py

的好例子

Node.py

Edge.py

我使用以下代码来实现这三个模块

--------- netxgui.py --------

import pandas as pd
from numpy import *
import sys
from math import *
from PyQt4 import QtCore,QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import networkx as nx
import GraphNetworkX
from x import *

pf = pd.read_csv('/desktop/companytrades.csv',header=0,index_col=['date'])

#setup the needed variables
if __names__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    app.setStyle("Plastique")

class netx(QtGui.QDialog):
    def __init__(self):
        super(netx,self).__init__()
        self.uiNX = Ui_Form() 
        self.uiNX.setupUi(self)
        G = nx.from_pandas_dataframe(pf,'Company1','Company2',create_using=nx.DiGraph())
Pos = nx.spring_layout(g,scale=300)
scene = GraphNetworkx.GraphGraphicsScene(G=g,pos=Pos)
self.uiNX.neworkx_graphicsView.setScene(scene)

NX = netx()
NX.show()
sys.exit(exit(app.exec_())
app.deleteLater()

------- x.py -------

from PyQt4 import QtCore,QtGui
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.unicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(1492,1029)
        self.networkx_graphicsView = QtGui.QGraphicsView(Form)
        self.networkx_graphicsView.setGeometry(QtCore.QRect(240,70,971,911))
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(5)
        sizePolicy.setHeightForWidth(self.networkx_graphicsView.sizePolicy().hasHeightForWidth())
        self.networkx_graphicsView.setSizePolicy(sizePolicy)
        self.networkx_graphicsView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.networkx_graphicsView.setObjectName(_fromUtf8("networkx_graphicsView"))
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)
    def retranslateUi(self,Form):
        Form.setWindowTitle(_translate("Form","Form",None))

我遇到了实施此问题的问题。我遇到的问题是在drawGraph函数下的GraphNetworkX中。打印功能似乎正常,但我真的不明白用i替换它的原因。

    i = 0
    for n in G.nodes():
        #print str(pos[n][0]) + " " + str(pos[n][1])+ " "+str(n)
        self.addNode(pos[i][0], pos[i][1], n)
        i += 1

我做了一个用n替换i的实验,并且添加节点似乎工作但是我在添加边缘时遇到了问题。

    for e in G.edges():
        node1 = self.nodes[e[0]]
        node2 = self.nodes[e[1]]
        self.addEdge(node1, node2)

它一直说e [0]超出范围。考虑Nodes.py函数是将self.nodes转换为Nodes.nodes对象列表,我想也许这是每个对象中的占位符但我不太确定。然后我尝试进行此更改:

node1 = e[0]
node2 = e[1] 

但是我在Edge.py中收到错误说明

 x1 = node1.centerX() 

整数没有函数centerX()

我有点不知所措。有人可以帮助我理解这一点并帮助我实现这一目标吗?

1 个答案:

答案 0 :(得分:1)

一个更小的问题可能有助于获得答案。 (例如,你x.py的任何内容似乎与问题最终无关)

为了帮助您入门,您可能会遇到一些名称空间重载(重命名相同的对象)。在netxgui.py中,您有import networkx as nx,但稍后您会声明一个类nx(QtGui.QDialog)。在此之后,您尝试拨打nx.spring_layout()您可能想要来自networkx而非您的自定义nx类。您尝试访问的结构可能存在于networkx Graph实例中但不存在于QDialog实例中?

一般而言,避免使用from examplemodule import *会让您在尝试追踪错误或开发代码时更轻松。

--- 编辑 ---

我仔细观察了问题是因为networkx.Graph / .DiGraph等和GraphGraphicsScene中使用的表示方式不同。 Networkx使用下面的词典来存储节点(以及边缘)。 GraphGraphicsScene使用列表节点。

快速而肮脏的解决方案:这些发生兼容,如果您的节点标记为从0开始,并且具有连续的序列。

稍微更健壮的是生成这样的图形,可以通过以下方式实现:

def re_index_digraph(G_orig):
    remap = {i: n for (i,n) in enumerate(G_orig.nodes())}
    inv_remap = {v:k for k,v in remap.items()}
    G = nx.DiGraph()
    G.add_nodes_from(remap)
    remap_edges = [(inv_remap[src], inv_remap[sink]) for (src, sink) in G_orig.edges()]
    G.add_edges_from(remap_edges)
    return G

G_orig = nx.from_pandas_dataframe(pf,'Company1','Company2',create_using=nx.DiGraph())
G = re_index_digraph(G_orig)

然后像往常一样继续G。 (如果除了节点名称和边缘之外还有其他属性,则需要相应地扩展重映射功能。)

除此之外,您可能需要投入大量精力来开发GraphGraphicsScene实施。