洛伦谈MATLAB的艺术

将想法转化为MATLAB

MATLAB Python说话

MATLAB是一个伟大的计算环境的工程师和科学家。MATLAB还提供了对通用语言的访问,包括C/ c++、Java、Fortran、。net和Python。今天的嘉宾博客竹内俊二,我想谈谈MATLAB与Python的结合使用

内容

为什么不两者都用呢?

当我们讨论语言时,我们经常会遇到错误的选择在您觉得必须选择一种或另一种的情况下。实际上,您通常可以同时使用这两种语言。我们大多数人都不是单独工作的。作为更大团队的一部分,您的工作通常是涉及多种语言的更大工作流的一部分。这就是为什么MATLAB提供了与包括Python在内的其他语言的互操作性。您的同事可能希望利用y我们的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;如果体育状况==“未加载”[~,exepath]=系统(“巨蟒”);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的复杂网络包。我们可以很容易地开始使用这个包导入数据集。

我使用的是NetworkX 2.2。要在Python中检查包的版本,你通常会像这样使用version package属性:

>>>networkx.\uuuu版本__

MATLAB不支持万博1manbetx类名或其他以下划线(_)开头的标识符.相反,使用下面的方法获取包的帮助内容,包括它的当前版本。

>救命啊(“networkx”)

导入还是不导入

通常,您可以在Python脚本的开头执行此操作。

进口networkxnxG = nx.karate_club_graph ()

然而,这在MATLAB中不推荐,因为行为进口函数在MATLAB中是不同于Python的。

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

nxG = py.networkx.karate_club_graph ();

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

进口py.networkx*nxG = karate_club_graph ();

正如您所看到的,当您省略时,很难记住我们正在调用Python方法py,当您开始在同一个脚本中混合MATLAB代码和Python代码时,可能会感到困惑。

从Python对象提取数据

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

myDataType =类(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 '

现在埃德格尔包含一个Python列表存储为Python的节点对元组元素。每个节点对表示图中的一条边。让我们看看前5个元组值。

listContent = edgeL (1:5)
listContent=Python列表,没有属性。[(0,1)、(0,2)、(0,3)、(0,4)、(0,5)]

处理Python列表和元组

Python处理列表元组通常看起来像这样,在循环中处理单个元素。

对于我在李:打印#L这个列表对于u、 五师:打印((u, v))#T这个元组

MATLAB的方法是使用数组。巨蟒列表可以转换成细胞数组中。

edgeC=单元格(edgeL);myDataType=类(edgeC)
myDataType='cell'

细胞数组包含Python元组元素。

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

巨蟒元组也可以转换为细胞数组。转换内部元组元素,我们可以使用赛尔芬

edgeC=cellfun(@cell,edgeC,“UniformOutput”、假);myDataType =类(edgeC {1})
myDataType='cell'

由此产生的嵌套细胞数组包含Pythonint值。

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

处理Python字典

现在,让我们也从数据集中提取节点。我们可以按照处理边的相同步骤进行操作。

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

内心细胞数组包含两个Pythonint字典元素。

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

python字典是基于键值对的数据类型。在本例中,键为“俱乐部”它的值是“你好,先生”

cellContent=nodeC{1}{2}
cellContent =没有属性的Python字典。{“俱乐部”:“你好先生”}

Hi先生是俱乐部的空手道教练。Python中的另一个值字典“官”,而那位军官是俱乐部的领导。他们是各自派系的关键人物。节点属性表示单个节点属于哪个派系。在这个案例中,Node 1属于Hi先生的派系。

Python处理字典通常看起来像这样,在循环中处理单个元素。

对于k、vd.items ():印刷品(k,v)

同样,MATLAB的方法是使用数组字典可以转换为结构体数组中。

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

我们可以将单个值提取到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还提供了图形和网络功能我们可以用它们来形象化这个图像。

让我们把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=节点ATTRS';图P1=绘图(G);高亮显示(P1,组,“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 =类(myListofTuples {1})
myDataType='py.tuple'

让我们从MATLAB中提取边列表图表.它是一个78x2的矩阵双重的值。在MATLAB中,双重的是默认的数字数据类型。

edgeL = G.Edges.EndNodes;myDataType =类(edgeL)
myDataType =“双”

如果我们转换数组双重的给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=class(edgeL)
myDataType='int8'

我们可以使用num2cell转换的矩阵int8值为78x2细胞数组,其中每个元素位于单独的单元格中。

edgeL=num2单元格(edgeL);myDataType=class(edgeL)
myDataType='cell'

我们可以通过转换78x2将节点对放置在同一个单元格中细胞数组到78x1细胞数组的使用num2cell

edgeL = num2cell (edgeL 2);(行,关口)=大小(edgeL)
行= 78 cols = 1

这个添加\u边\u自方法需要一个1xN Python列表.现在,让我们将其转换为1xN细胞通过转置Nx1数组细胞数组,将其转换为Python列表并将其添加到空的NetworkX图形对象中。

nxG2.add_edges_from (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, {})]

要添加属性,我们需要使用set_node_attributes此方法需要一个嵌套的Python字典.这里是如何创建一个字典在MATLAB。

myDict = py.dict (pyargs (“钥匙”,“价值”))
myDict =没有属性的Python字典。{“关键”:“价值”}

这个set_node_attributes方法需要一个嵌套的字典. 外钥匙字典是节点,值是字典数组键值对如下:

{0: {“俱乐部”:“你好,先生”}, 1: {“俱乐部”:“官”}}

不幸的是,这行不通,因为皮亚格斯只需要一个字符串烧焦以价值为关键。

> > py。字典(pyargs(0, py.dict(pyargs(“俱乐部”,“你好,先生”))))错误使用皮亚格斯领域的名字必须字符串标量字符向量。

相反,我们可以创建一个空的字典,并添加内部字典元组数据,使用基于0的索引,具有更新方法如下:

attrsD = py.dict;对于ii=1:length(nodeAttrs)attrD=py.dict(pyargs(“俱乐部”G.Nodes.club (ii)));attrsD.update (py。元组({{int8(ii - 1), attrD}}))终止

然后我们可以用set_node_attributes向节点添加属性。

py.networkx.set\u node\u属性(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.贪婪的模块化社区(nxG2);myDataType=class(communitiesL)
myDataType = ' py.list '

返回的Python列表包含三个元素。这意味着算法在这个图中检测到了3个社区。

num_communitieis =长度(communitiesL)
社区数量=3

这个列表包含一个frozenset.蟒蛇frozenset与Python相同设置,除了它的元素是不可变的之外设置类似于Python列表,但它的所有元素都是唯一的,而a列表可以多次包含同一元素。

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(communitiesC)communitiesC{ii}=cellfun(@double,communitiesC{ii});终止myDataType =类(communitiesC {1} (1))
myDataType =“双”

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

cellfun(@(x) x + 1,“UniformOutput”、假);

让我们在图中画出社区。

平铺布局(1,2)下一层P1=绘图(G);高亮显示(P1,组,“NodeColor”,"D95319",“EdgeColor”,"D95319")标题({圣扎迦利”年代空手道俱乐部,“橙色代表Hi先生的派系”}) nexttile P2 = plot(G);突出(P2, communitiesC {1},“NodeColor”,“#0072BD”,“EdgeColor”,“#0072BD”)突出显示(P2,社区C{2},“NodeColor”,"D95319",“EdgeColor”,"D95319")突出(P2, communitiesC {3},“NodeColor”,“# 77 ac30”,“EdgeColor”,“# 77 ac30”)标题({圣扎迦利”年代空手道俱乐部,“基于模块化的社区”})

如果你比较一下这些地块,你会发现右边橘色和绿色的两个社区结合在一起时,大致与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”、假);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();edgeL=num2单元(int8(G.Edges.EndNodes)-1);nxG2.从(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_属性(nxG2,attrsD);

为了检测社区,你可以这样做:

社区C=cell(py.networkx.algorithms.community.贪婪的模块化社区(nxG2));社区C=cellfun(@(x)单元格(py.list(x)),社区C,“UniformOutput”、假);对于ii=1:length(communitiesC)communitiesC{ii}=cellfun(@double,communitiesC{ii});终止cellfun(@(x) x + 1,“UniformOutput”、假);

总结

在这个例子中,我们看到了如何在MATLAB中使用Python。一旦理解了数据类型转换是如何工作的,就非常简单了。事情要记住:

  • Python是基于0的索引而MATLAB是基于1的索引
  • Python的默认数值数据类型为int而这是双重的对MATLAB
  • 将Python数据转换成适合的MATLAB数组,而不是循环
  • 使用细胞Python的数组列表元组
  • 使用结构体Python的数组字典

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

你是编码通晓者吗?分享你如何一起使用MATLAB和Python在这里




发布与MATLAB®R2019b

|

评论

要留下评论,请点击在这里登录到您的MathWorks帐户或创建一个新帐户。