MATLAB讲Python
Matlab是工程师和科学家的伟大计算环境。MATLAB还提供对通用语言的访问,包括C / C ++,Java,Fortran,.NET和Python。今天的客人博主,竹内俊二,想谈谈MATLAB与Python的结合使用.
内容
为什么不两者都用呢?
当我们讨论语言时,我们经常会遇到错误的选择你觉得你必须选择其中之一。实际上,两者都可以使用。我们大多数人都不是独自工作的。作为更大团队的一部分,您的工作通常是包含多种语言的更大工作流的一部分。这就是为什么MATLAB提供了与其他语言(包括Python)的互操作性。您的同事可能想利用您的MATLAB代码,或者您需要从IT系统访问基于python的功能。MATLAB支万博1manbetx持您的工作流程在两个方向。
今天我想重点谈谈从MATLAB调用Python在基于MATLAB的工作流中利用一些现有的Python功能。
在这篇文章中,我们将看到:
- 如何将Python中的数据导入MATLAB
- 如何从MATLAB传递数据到Python
- 如何在Matlab中使用Python包
在MATLAB中建立Python
MATLAB支万博1manbetx持Python 2.7, 3.6和3.7在撰写本文时(R2019b)。这里是另一个有用的关联.
我假设您已经知道如何安装和管理您选择的平台上的Python环境和依赖项,在这里我将不讨论它,因为它本身就是一个复杂的主题。
让我们在MATLAB中启用对Python的访问。您需要找到Python可执行文件的完整路径。下面是一个Windows示例。在Mac和Linux上,您的操作系统命令可能不同。
pe = pyenv;如果体育状况==“NotLoaded”[~,exepath]=系统(“巨蟒”);pe=pyenv(“版本”, exepath);终止
如果这不起作用,还可以将路径作为字符串传递给Python可执行文件。
pe = pyenv (“版本”,'C:\Users\username\AppData\Local\your\python\path\python.exe')
mypythonversion = pe.version py.print(“你好,Python!”)
myPythonVersion=“3.7”你好,Python!
空手道俱乐部
韦恩·扎卡里发表了一数据集该网站包含了20世纪70年代美国一所大学空手道俱乐部的34名成员之间的友谊社交网络。这个俱乐部里爆发的一场争执最终使它分裂成两个派别。我们想看看,我们是否能根据俱乐部的人际关系,用算法来预测俱乐部将如何解体。
这个数据集包含在NetworkX,一个用于Python的复杂网络包。我们可以很容易地开始使用这个包导入数据集。
我使用的是NetworkX 2.2。要在Python中检查包的版本,你通常会像这样使用version package属性:
>>>networkx.\uuuu版本__
MATLAB不支持万博1manbetx类名或其他以下划线(_)开头的标识符。请使用以下命令获取软件包上的帮助内容,包括其当前版本。
>救命啊(“networkx”)
导入还是不导入
通常,在Python脚本开始时执行此操作。
进口networkx像nxG=nx.空手道俱乐部图()
然而,这在MATLAB中不推荐,因为行为进口函数在MATLAB中是不同于Python的。
MATLAB调用Python的方法是使用派克,后面跟着一个包或方法,如下所示:
nxG=py.networkx.karate_club_graph();
如果必须使用进口,您可以按如下方式执行:
进口py.networkx*nxG = karate_club_graph ();
如您所见,当省略时,很难记住我们正在调用Python方法派克,当您开始在同一个脚本中混合使用MATLAB代码和Python代码时,这可能会令人困惑。
从Python对象提取数据
以下代码返回NetworkX图形对象中的空手道俱乐部数据集。
myDataType=class(nxG)
myDataType='py.networkx.classes.graph.graph'
您可以看到此对象上可用的方法,如下所示:
方法(nxG)
您还可以查看此对象的属性。
属性(nxG)
NetworkX图形包含边缘属性,该属性返回被调用的对象EdgeView.
edgeL = nxG.edges;myDataType =类(edgeL)
myDataType='py.networkx.classes.reportviews.EdgeView'
要在MATLAB中使用此Python对象,第一步是将该对象转换为核心Python数据类型,如Python列表.
edgeL=py.list(edgeL);myDataType=class(edgeL)
myDataType='py.list'
现在edgeL包含一个Python列表存储为Python的节点对元组元素。每个节点对表示图中的一条边。让我们看看前5条元组值。
listContent = edgeL (1:5)
listContent =没有属性的Python列表。[(0,1), (0,2), (0,3), (0,4), (0,5)]
处理Python列表和元组
Python处理列表或元组通常是这样的,在循环中处理单个元素。
对于我在李:打印我#L是这个列表对于u、 五在t:打印((u, v))#T是这个元组
Matlab方式是使用数组。巨蟒列表可以转换成细胞数组中。
edgeC=单元格(edgeL);myDataType=类(edgeC)
myDataType =“细胞”
这细胞数组包含Python元组元素。
myDataType =类(edgeC {1})
myDataType='py.tuple'
巨蟒元组也可以转换为细胞数组。转换内部元组元素,我们可以使用cellfun.
= cellfun(@cell, edgeC,“UniformOutput”、假);myDataType =类(edgeC {1})
myDataType =“细胞”
结果是嵌套的细胞数组包含Python㈡值。
myDataType =类(edgeC {1} {1})
myDataType = ' py.int '
处理python dict
现在让我们也从数据集中提取节点。我们可以按照边的步骤来做。
nodeL=py.list(nxG.nodes.data);nodeC=cell(nodeL);nodeC=cellfun(@cell,nodeC,“UniformOutput”、假);
一个内细胞数组包含两个Python㈡和dict元素。
cellContent=nodeC{1}
CellContent = 1×2单元阵列{1×1 py.int} {1×1 py.dict}
Pythondict是基于键值对的数据类型。在这种情况下,关键是“俱乐部”价值是“你好先生”.
cellContent=nodeC{1}{2}
cellContent =没有属性的Python字典。{“俱乐部”:“你好先生”}
嗨先生是俱乐部的空手道教练。Python中的另一个值dict是“警官”,而那位军官是俱乐部的领导。他们是各自派系的关键人物。节点属性表示单个节点属于哪个派系。在这个案例中,Node 1属于Hi先生的派系。
Python处理dict通常是这样的,在循环中处理单个元素。
对于k、v在d、 项目():打印(k、v)
同样,MATLAB的方法是使用数组dict可以转换为结构体数组中。
nodeAttrs=cellfun(@(x)struct(x{2}),nodeC);myDataType=class(nodeAttrs)
mydatatype ='struct'
我们可以将单个值提取到a中一串这个俱乐部显然在各派之间平分。
nodeAttrs=arrayfun(@(x)字符串(x.club),nodeAttrs;制表(nodeAttrs)
价值计数百分比Hi先生17 50.00%官员17 50.00%
我们把Hi先生阵营的节点取出来。
Group_hi = 1:长度(Nodeattrs);group_hi = group_hi(nodeattrs ==“你好先生”);
在MATLAB中可视化图形
MATLAB还提供图形和网络功能我们可以用它们来可视化图形。
让我们把Python㈡要删除的边列表中的值双并将边中的节点提取为独立的向量。
s = cellfun(@(x) double(x{1}), edgeC);t = cellfun(@(x) double(x{2}), edgeC);
MATLAB图表需要节点的列向量。让我们转置它们。
s=s’;t=t’;
Python中的节点索引以0开始,但在MATLAB中节点索引必须以非零值开始。让我们来解决这个问题。
s = s + 1;t = t + 1;
现在,我们准备创建一个MATLAB图形对象并绘制它,突出显示Hi先生的派系。
图G = (s, t);G.Nodes.club = nodeAttrs ';图P1 = plot(G);突出(P1, group_hi,“NodeColor”,"D95319",“EdgeColor”,"D95319")标题({圣扎迦利”年代空手道俱乐部,'Orange代表嗨先生的派系'})
将数据从MATLAB传递到Python
在本例中,我们已经有了NetworkX图形对象,但是为了完整性,让我们看看如何在MATLAB中创建这个Python对象。
让我们创建一个空的NetworkX图。
nxG2 = py.networkx.Graph ();
您可以使用添加\u边\u自方法。它接受Python列表属于元组像这样的元素:
[(1、2),(2,3),(3、4)
这在MATLAB中不是一个有效的语法。我们可以用1xN细胞像这样的节点对数组:
myListofTuples={{1,2},{2,3},{3,4};
当我们传递这个嵌套细胞数组来py.list,Matlab会自动将其转换为Python列表属于元组元素。
myListofTuples=py.list(myListofTuples);myDataType=class(myListofTuples{1})
myDataType='py.tuple'
让我们从MATLAB中提取边列表图表.这是一个78x2的矩阵双在MATLAB中,双是默认的数字数据类型。
edgeL = G.Edges.EndNodes;myDataType =类(edgeL)
myDataType =“双”
如果我们将双给Python的值列表,这些值将被转换为Python浮动,但Python中的默认数字数据类型为㈡.所以我们不能使用双.
listContent=py.list(edgeL(1,:))
listContent=不带属性的Python列表。[1.0, 2.0]
此外,Python的索引是基于0的,而MATLAB是基于1的。我们需要转换数组双要素int8并将变量元素更改为基于0的索引。
edgeL = int8(edgeL) - 1;myDataType =类(edgeL)
myDataType = ' int8 '
我们可以使用num2cell转换矩阵int8将值转换为78x2细胞数组,其中每个元素位于单独的单元格中。
edgeL=num2单元格(edgeL);myDataType=class(edgeL)
myDataType =“细胞”
通过转换78x2,我们可以将节点对放置在同一个单元中细胞数组到78x1细胞数组使用num2cell.
edgeL = num2cell (edgeL 2);(行,关口)=大小(edgeL)
行= 78 cols = 1
这个添加\u边\u自方法需要一个1xN Python列表.现在,让我们将其转换为1xN细胞通过转置Nx1数组细胞数组,将其转换为python列表并将其添加到空的NetworkX图形对象中。
nxG2.从(py.list(edgeL'))添加边;
边缘被添加到NetworkX图形对象中。让我们看看前5个元组值。
edgeL=py.list(nxG2.edges);listContent=edgeL(1:5)
listContent =没有属性的Python列表。[(0,1), (0,2), (0,3), (0,4), (0,5)]
这些节点也被添加到图中,但它们当前没有任何属性,正如您在下面节点列表的前3个元素中看到的那样。
nodeL = py.list (nxG2.nodes.data);listContent = nodeL (1:3)
listContent=不带属性的Python列表。[(0,{},(1,{},(2,{})]
要添加属性,我们需要使用设置节点属性此方法需要一个嵌套的Pythondict.这里是如何创建一个dict在MATLAB。
myDict=py.dict(pyargs(“钥匙”,“价值”))
myDict=没有属性的Python dict。{'key':'value'}
这个设置节点属性方法需要一个嵌套的dict.外面的钥匙dict节点和值是dict数组这样的键值对的数目:
{0: {“俱乐部”:“你好先生”1}: {“俱乐部”:“警官”}}
不幸的是,这行不通,因为pyargs希望只有一个一串或字符以价值为关键。
> > py。dict(pyargs(0, py.dict(pyargs(“俱乐部”,“你好先生”))))错误使用pyargs领域的名字必须是一串标量或性格向量。
相反,我们可以创建一个空的dict,并添加内部dict从元组数据,使用基于0的索引使现代化方法是这样的:
attrsD=py.dict;对于ii=1:length(nodeAttrs)attrD=py.dict(pyargs(“俱乐部”G.Nodes.club (ii)));attrsD.update (py。元组({{int8(ii - 1), attrD}}))终止
然后我们可以使用设置节点属性向节点添加属性。
py.networkx.set_node_attributes (nxG2 attrsD);nodeL = py.list (nxG2.nodes.data);listContent = nodeL (1:3)
listContent=不带属性的Python列表。[(0,{'club':'Mr.Hi'}),(1,{'club':'Mr.Hi'}),(2,{'club':'Mr.Hi'}]
NetworkX社区检测
NetworkX提供了贪婪_Modularity_Communities.方法在图中查找社区。让我们试试这个算法,看看它能多好地检测派系!
由于这个俱乐部分成了两个小组,我们希望看到两个社区。
communitiesL = py.networkx.algorithms.community.greedy_modularity_communities (nxG2);myDataType =类(communitiesL)
myDataType='py.list'
返回的Python列表包含三个元素。这意味着算法在这个图中检测到了3个社区。
num_communitieis =长度(communitiesL)
num_communitieis = 3
这个列表包含冻结.一条巨蟒冻结和Python一样吗设置,除了它的元素是不可变的之外设置类似于Python列表,但其所有元素都是唯一的,而列表可以多次包含同一元素。
listContent = communitiesL {1}
listContent=Python冻结集,不带属性。frozenset({32,33,8,14,15,18,20,22,23,24,25,26,27,28,29,30,31})
让我们把它转换成嵌套的细胞.
社区C=单元(社区L);社区C=单元F(@(x)单元(py.list(x)),社区C,“UniformOutput”,false);myDataType=class(社区C{1}{1})
myDataType = ' py.int '
内心最细胞包含Python㈡值。我们把它们转换成双.
对于ii = 1:length(communtiesc) communtiesc {ii} = cellfun(@double, communtiesc {ii});终止myDataType =类(communitiesC {1} (1))
myDataType =“双”
因为在Python中节点是基于0的索引,所以我们需要在MATLAB中将它们改为基于1的索引。
社区c=cellfun(@(x)x+1,社区c,“UniformOutput”、假);
让我们在图中画出社区。
P1 = plot(G);突出(P1, group_hi,“NodeColor”,"D95319",“EdgeColor”,"D95319")标题({圣扎迦利”年代空手道俱乐部,'Orange代表嗨先生的派系'}) nexttile P2 = plot(G);突出(P2, communitiesC {1},“NodeColor”,“# 0072 bd”,“EdgeColor”,“# 0072 bd”)突出显示(P2,社区C{2},“NodeColor”,"D95319",“EdgeColor”,"D95319")突出(P2, communitiesC {3},“NodeColor”,'#77ac30',“EdgeColor”,'#77ac30')标题({圣扎迦利”年代空手道俱乐部,“基于模块化的社区”})
如果你比较一下这些地块,你会发现右边橘色和绿色的两个社区结合在一起时,大致与Hi先生的派系重叠。
我们还可以看到:
- 社区1代表“军官”派系
- 社区3代表忠诚的“Hi先生”派系
- 社区2代表与两派都有联系的人
有趣的是,社区2最终站在了Hi的阵营一边。
让我们看看算法的输出和实际的派系之间是否有任何差异。
diff_elements = setdiff(group_hi, [communtiesc {2} communtiesc {3}]);diff_elements = [diff_elements setdiff([communtiesc {2} communtiesc {3}], group_hi)]
差异元素=9 10
社区检测算法非常接近于识别实际派系。
精简的代码
到目前为止,我们一直在检查每个步骤中返回的数据类型。如果您已经知道数据类型,您可以将这些步骤组合成几行代码。
要获得空手道俱乐部的数据并创建一个MATLAB图,你可以这样做:
nxG=py.networkx.karate_club_graph();edgeC=cellfun(@cell,cell(py.list(nxG.edges)),“UniformOutput”,false);nodeC=cellfun(@cell,cell(py.list(nxG.nodes.data)),“UniformOutput”、假);nodeAttrs = cellfun(@(x) struct(x{2}), nodeC);nodeAttrs = arrayfun(@(x) string(x.club), nodeAttrs);s = cellfun(@(x) double(x{1}), edgeC)' + 1;t = cellfun(@(x) double(x{2}), edgeC)' + 1;图G = (s, t);G.Nodes.club = nodeAttrs ';
要从MATLAB数据创建一个Python图形,你可以这样做:
nxG2 = py.networkx.Graph ();= num2cell(int8(g.r egs . endnodes) - 1);nxG2.add_edges_from (py。列表(num2cell(edgeL, 2)')); attrsD = py.dict;对于ii = 1:length(G.Nodes.club) attrD = py.dict(pyargs(“俱乐部”G.Nodes.club (ii)));attrsD.update (py。元组({{int8(ii - 1), attrD}}))终止py.networkx.set_node_attributes (nxG2 attrsD);
要检测社区,可以这样做:
社区C=cell(py.networkx.algorithms.community.贪婪的模块化社区(nxG2));社区C=cellfun(@(x)单元格(py.list(x)),社区C,“UniformOutput”、假);对于ii = 1:length(communtiesc) communtiesc {ii} = cellfun(@double, communtiesc {ii});终止社区c=cellfun(@(x)x+1,社区c,“UniformOutput”、假);
概括
在本例中,我们了解了如何在MATLAB中使用Python。一旦您了解了数据类型转换的工作原理,这就相当简单了。要记住的事项:
- Python是基于0的索引而MATLAB是基于1的索引
- Python的默认数值数据类型为㈡而它是双对于MATLAB
- 将Python数据转换为适当类型的MATLAB数组,而不是循环
- 使用细胞Python的数组列表和元组
- 使用结构体Python的数组dict
在本例中,我们在MATLAB工作流中使用Python库来获取数据和检测社区。我本可以在MATLAB中编写所有代码,但利用现有Python代码更容易,并且我能够在熟悉的MATLAB环境中完成任务,在那里我可以最高效地完成任务。
你是一个多才多艺的程序员吗?分享你是如何使用MATLAB和Python的这里.
评论
如需留言,请点击这里登录到您的MathWorks帐户或创建新帐户。