洛伦谈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]=系统(“巨蟒”);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脚本开始时执行此操作。

进口networkxnxG=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”、假);

一个内细胞数组包含两个Pythondict元素。

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、vd、 项目():打印(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的这里




发布与MATLAB®R2019b

|

评论

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