罗兰谈MATLAB的艺术

将想法转化为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] = system(“巨蟒”);PE = pyenv(“版本”, exepath);结束

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

PE = pyenv(“版本”“C: \ \用户名\ AppData \用户当地\ \ python \路径\ python.exe
mpyythonversion = pe。版本py.print (“你好,Python !”
mpyythonversion = "3.7"你好,Python!

空手道俱乐部数据集

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

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

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

> > > networkx.__version__

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

> py.help (“networkx”

进口还是不进口

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

进口networkx作为nxG = x.karate_club_graph()

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

MATLAB中调用Python的方法是使用py,后面跟着一个包或方法,像这样:

nxG = py.network .karate_club_graph();

如果你必须使用进口,你可以这样做:

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

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

从Python对象中提取数据

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

myDataType =类(nxG)
myDataType = 'py.network .classes.graph. graph '

你可以像这样看到这个对象上可用的方法:

方法(nxG)

您还可以看到该对象的属性。

属性(nxG)

NetworkX图包含边缘属性,该属性返回名为EdgeView

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列表u, v师:打印((u, v))t元组

MATLAB的方法是用数组代替。Python列表可以转换成细胞数组中。

edgeC = cell(edgeL);myDataType = class(edgeC)
myDataType = 'cell'

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

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

Python元组也可以转换成细胞数组中。来转换内部元组元素,我们可以使用cellfun

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

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

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

处理Python字典

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

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

一个内细胞数组包含int而且dict元素。

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

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

cellContent = nodeC{1}{2}
cellContent =没有属性的Python字典。{'club': 'Mr. Hi'}

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

处理的Python方法dict通常看起来像这样,在循环中处理单个元素。

k、vd.items ():打印(k, v)

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

nodeAttrs = cellfun(@(x) struct(x{2}), nodeC);myDataType = class(节点类型)
myDataType = 'struct'

我们可以把单独的值提取到a中字符串数组中。俱乐部里的派系显然平分秋色。

nodeAttrs = arrayfun(@(x) string(x.club), nodeAttrs);汇总(nodeAttrs)
价值计数百分比先生嗨17 50.00%官员17 50.00%

我们把Hi先生阵营的节点提取出来。

group_hi = 1:length(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 =图(G);突出(P1, group_hi,“NodeColor”“# D95319”“EdgeColor”“# D95319”)标题({“扎卡里的空手道俱乐部”“橙色代表Hi先生的派系”})

将数据从MATLAB传递到Python

在本例中,我们已经有了NetworkX图形对象,但是为了完整起见,让我们看看如何在MATLAB中创建这个Python对象。

让我们创建一个空的NetworkX图。

nxG2 = py.networkx.Graph();

属性可以向此图形添加边add_edges_from方法。它接受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 = class(edgeL)
myDataType = 'int8'

我们可以用num2cell变换矩阵int8值为78x2细胞数组,其中每个元素都在一个单独的单元格中。

edgeL = num2cell(edgeL);myDataType = class(edgeL)
myDataType = 'cell'

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

edgeL = num2cell(edgeL,2);[rows,cols] = size(edgeL)
Rows = 78 cols = 1

add_edges_from方法需要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方法。此方法需要一个嵌套的Pythondict.下面是如何创建一个dict在MATLAB。

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

set_node_attributes方法需要一个嵌套的dict.外部的钥匙dict节点是,值是dict数组像这样的键值对:

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

不幸的是,这行不通,因为pyargs只期望字符串字符Value作为键。

> > 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}}))结束

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

py.networkx.set_node_attributes (nxG2 attrsD);nodeL = py.list(nxG2.nodes.data);listContent = nodeL(1:3)
listContent =没有属性的Python列表。((0,{“俱乐部”:“你好先生”}),(1,{“俱乐部”:“你好先生”}),(2){“俱乐部”:“你好先生”}))

使用NetworkX进行社区检测

NetworkX提供greedy_modularity_communities方法在图中查找团体。让我们试试这个算法,看看它能多好地检测派系!

由于这个俱乐部分成了两个小组,我们希望看到两个社区。

communtiesl = py.network .algorithms.community.greedy_modularity_communities(nxG2);myDataType = class(communtiesl)
myDataType = 'py.list'

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

num_communtieis = length(communtiesl)
num_communtieis = 3

列表包含一个frozenset.一条巨蟒frozenset和Python是一样的吗,除了它的元素是不可变的。和蟒蛇类似于Python列表,除了它的所有元素都是唯一的,而a列表可以多次包含同一元素。

listContent = communtiesl {1}
listContent =没有属性的Python frozenset。Frozenset ({32, 33, 8, 14, 15, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31})

让我们把它转换成嵌套的细胞

communtiesc = cell(communtiesl);communtiesc = cellfun(@(x) cell(py.list(x)), communtiesc,“UniformOutput”、假);myDataType = class(communtiesc {1}{1})
myDataType = 'py.int'

内心最深处细胞包含Pythonint值。我们把它们转换成

ii = 1:length(communtiesc) communtiesc {ii} = cellfun(@double, communtiesc {ii});结束myDataType = class(communtiesc {1}(1))
myDataType = 'double'

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

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

让我们在图中绘制社区。

tiledlayout(1,2) nexttile P1 = plot(G);突出(P1, group_hi,“NodeColor”“# D95319”“EdgeColor”“# D95319”)标题({“扎卡里的空手道俱乐部”“橙色代表Hi先生的派系”}) nexttile P2 = plot(G);突出(P2, communitiesC {1},“NodeColor”“# 0072 bd”“EdgeColor”“# 0072 bd”(P2, communtiesc {2},“NodeColor”“# D95319”“EdgeColor”“# D95319”(P2, communtiesc {3},“NodeColor”“# 77 ac30”“EdgeColor”“# 77 ac30”)标题({“扎卡里的空手道俱乐部”“Modularity-based社区”})

如果你对比这些图,你可以看到右边橙色和绿色的两个社区,当结合起来时,大致与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)]
Diff_elements = 9

社区检测算法非常接近于识别实际的派系。

简化代码

到目前为止,我们一直在检查每个步骤中返回的数据类型。如果您已经知道了数据类型,那么可以将这些步骤合并到几行代码中。

要获得空手道俱乐部的数据并创建MATLAB图,您可以这样做:

nxG = py.network .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 = num2cell(int8(G.Edges.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);

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

communtiesc = cell(py.network .algorithms.community.greedy_modularity_communities(nxG2));communtiesc = cellfun(@(x) cell(py.list(x)), communtiesc,“UniformOutput”、假);ii = 1:length(communtiesc) communtiesc {ii} = cellfun(@double, communtiesc {ii});结束communtiesc = cellfun(@(x) x + 1, communtiesc,“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계정에로그하거나계정을새로만드십시오。