洛伦谈MATLAB的艺术

将想法转化为MATLAB

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]=系统(“python在哪里”);pe=pyenv(“版本”,exepath);终止

如果这不起作用,还可以将路径作为字符串传递给Python可执行文件。

pe=pyenv(“版本”,'C:\Users\username\AppData\Local\your\python\path\python.exe')
myPythonVersion =体育。版本py.print (“你好,Python!”)
myPythonVersion=“3.7”你好,Python!

空手道俱乐部

韦恩·扎卡里发表数据集该网站包含了20世纪70年代美国一所大学空手道俱乐部的34名成员之间的友谊社交网络。这个俱乐部里爆发的一场争执最终使它分裂成两个派别。我们想看看,我们是否能根据俱乐部的人际关系,用算法来预测俱乐部将如何解体。

此数据集包含在NetworkX,一个用于Python的复杂网络包。我们可以很容易地开始使用这个包导入数据集。

我正在使用Networkx2.2。要在Python中检查包的版本,通常会使用version-package属性,如下所示:

>>>networkx.\uuuu版本__

MATLAB不支持万博1manbetx类名称或以下划线(\)字符开头的其他标识符。请使用以下命令获取软件包上的帮助内容,包括其当前版本。

>救命啊(“networkx”)

导入还是不导入

通常,在Python脚本开始时执行此操作。

进口networkxnxG=nx.空手道俱乐部图()

但是,在MATLAB中不建议这样做,因为进口MATLAB中的函数与Python中的函数不同。

MATLAB调用Python的方法是使用派克,后面跟着一个包或方法,如下所示:

nxG=py.networkx.karate_club_graph();

如果必须使用进口,您可以按如下方式执行:

进口py.networkx*nxG=空手道俱乐部图();

如您所见,当省略时,很难记住我们正在调用Python方法派克,当您开始在同一个脚本中混合使用MATLAB代码和Python代码时,这可能会令人困惑。

从Python对象提取数据

以下代码返回NetworkX图形对象中的空手道俱乐部数据集。

myDataType=class(nxG)
myDataType='py.networkx.classes.graph.graph'

您可以看到此对象上可用的方法,如下所示:

方法(nxG)

您还可以查看此对象的属性。

属性(nxG)

NetworkX图形包含边缘属性,该属性返回被调用的对象艾奇维

edgeL=nxG.edges;myDataType=class(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:打印#L这个列表对于u、 五在里面t:打印((u,v))#T这个元组

MATLAB的方法是使用数组。巨蟒列表可以转换成单间牢房大堆

edgeC=单元格(edgeL);myDataType=类(edgeC)
myDataType =“细胞”

单间牢房数组包含Python元组元素。

myDataType =类(edgeC {1})
myDataType='py.tuple'

巨蟒元组也可以转换为单间牢房数组。转换内部元组元素,我们可以使用cellfun

= cellfun(@cell, edgeC,“UniformOutput”,false);myDataType=class(edgeC{1})
myDataType =“细胞”

结果是嵌套的单间牢房数组包含Pythonint值。

myDataType=class(edgeC{1}{1})
myDataType='py.int'

处理Python字典

现在让我们也从数据集中提取节点。我们可以按照边的步骤来做。

nodeL=py.list(nxG.nodes.data);nodeC=cell(nodeL);nodeC=cellfun(@cell,nodeC,“UniformOutput”、假);

一个内单间牢房数组包含两个Pythonintdict元素。

cellContent=nodeC{1}
cellContent = 1×2 cell array {1×1 py.int} {1×1 py.dict}

Pythondict是基于键值对的数据类型。在这种情况下,关键是“俱乐部”价值是“你好先生”

cellContent=nodeC{1}{2}
cellContent=Python dict,不带属性。{'club':'Mr.Hi'}

嗨先生是俱乐部的空手道教练。Python中的另一个值dict“警官”,该官员是俱乐部的领导人。他们是各自派系的关键人物。节点属性表示单个节点属于哪个派系。在本例中,节点1属于Hi先生的派系。

Python处理dict通常是这样的,在循环中处理单个元素。

对于k、 五在里面d、 项目():打印(k、v)

同样,MATLAB的方法是使用数组dict可以转换为结构大堆

nodeAttrs=cellfun(@(x)struct(x{2}),nodeC);myDataType=class(nodeAttrs)
myDataType =“结构”

我们可以将单个值提取到一串这个俱乐部显然在各派之间平分。

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还提供图形和网络功能我们可以用它们来可视化图形。

让我们转换Pythonint要删除的边列表中的值并将边中的节点提取为单独的向量。

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")头衔({“扎卡里空手道俱乐部”,“橙色代表Hi先生的派系”})

将数据从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=class(edgeL)
myDataType='double'

如果我们将Python的值列表,这些值将被转换为Python浮动,但Python中的默认数字数据类型为int.所以我们不能使用

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=num2单元(edgeL,2);[行,列]=大小(edgeL)
行=78列=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(“俱乐部”(二),;attrsD.update(py.tuple({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提供greedy_modularity_communities方法在图中查找社区。让我们试试这个算法,看看它能多好地检测派系!

由于该俱乐部分为两组,我们预计将看到两个社区。

communitiesL = py.networkx.algorithms.community.greedy_modularity_communities (nxG2);myDataType =类(communitiesL)
myDataType='py.list'

返回的Python列表包含3个元素。这意味着算法在该图中检测到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'

内心最单间牢房包含Pythonint值。我们把它们转换成

对于ii = 1:length(communtiesc) communtiesc {ii} = cellfun(@double, communtiesc {ii});终止myDataType=class(社区C{1}(1))
myDataType='double'

因为在Python中节点是基于0的索引,所以我们需要在MATLAB中将它们改为基于1的索引。

社区c=cellfun(@(x)x+1,社区c,“UniformOutput”、假);

让我们在图中绘制社区。

P1 = plot(G);突出(P1, group_hi,“NodeColor”,"D95319",“EdgeColor”,"D95319")头衔({“扎卡里空手道俱乐部”,“橙色代表Hi先生的派系”})nexttile P2=绘图(G);突出显示(P2,社区C{1},“NodeColor”,“# 0072 bd”,“EdgeColor”,“# 0072 bd”)突出显示(P2,社区C{2},“NodeColor”,"D95319",“EdgeColor”,"D95319")突出显示(P2,社区C{3},“NodeColor”,“# 77 ac30”,“EdgeColor”,“# 77 ac30”)头衔({“扎卡里空手道俱乐部”,“基于模块化的社区”})

如果你比较这些情节,你可以看到右边橙色和绿色的两个社区,当它们结合在一起时,大致与Hi先生的派系重叠。

我们还可以看到:

  • 社区1代表“军官”派系
  • 社区3代表忠诚的“Hi先生”派系
  • 社区2代表与两派都有联系的人

有趣的是,社区2最终站在了Hi的阵营一边。

让我们看看算法的输出和实际的派系之间是否有任何差异。

diff_elements=setdiff(组_hi,[communitiesC{2}communitiesC{3}]);diff_elements=[diff_elements setdiff([Communities C{2}Communities C{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”,false);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=graph(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(“俱乐部”(二),;attrsD.update(py.tuple({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的默认数字数据类型是int而它是对于MATLAB
  • 将Python数据转换为适当类型的MATLAB数组,而不是循环
  • 使用单间牢房Python的数组列表元组
  • 使用结构Python的数组dict

在本例中,我们在MATLAB工作流中使用Python库来获取数据和检测社区。我本可以在MATLAB中编写所有代码,但利用现有Python代码更容易,并且我能够在熟悉的MATLAB环境中完成任务,在那里我可以最高效地完成任务。

你是一个多才多艺的程序员吗?分享你是如何使用MATLAB和Python的在这里




与MATLAB®R2019b一起发布

|

评论

如需留言,请点击在这里登录到您的MathWorks帐户或创建新帐户。