MATLAB说Python
MATLAB对于工程师和科学家来说是一个很好的计算环境。MATLAB还提供对通用语言的访问,包括C/ c++、Java、Fortran、。net和Python。今天的客座博主,古原竹内我想谈谈使用MATLAB和Python.
内容
为什么不两者都用呢?
当我们讨论语言时,我们经常会遇到一个问题错误的选择你觉得你必须选择其中之一。实际上,您通常可以同时使用这两种方法。我们大多数人都不是独自工作的。作为更大团队的一部分,您的工作通常是涉及多种语言的更大工作流程的一部分。这就是为什么MATLAB提供了与包括Python在内的其他语言的互操作性。您的同事可能想要利用您的MATLAB代码,或者您需要从IT系统访问基于python的功能。MATLAB支金宝app持两个方向的工作流。
今天我想重点讲的是从MATLAB调用Python在基于matlab的工作流中利用一些现有的Python功能。
在这篇文章中,我们将看到:
- 如何从Python导入数据到MATLAB
- 如何将数据从MATLAB传递到Python
- 如何在MATLAB中使用Python包
在MATLAB中设置Python
MATLAB支金宝app持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)
myPythonVersion = pe。版本py.print (“你好,Python !”)
myPythonVersion = "3.7"你好,Python!
空手道俱乐部数据集
韦恩·扎卡里发表了一数据集它包含了20世纪70年代美国一所大学空手道俱乐部34名成员之间的友谊社交网络。这个俱乐部爆发了一场争论,最终导致它分裂成两个派别。我们想看看能否通过算法根据人际关系预测俱乐部会如何解散。
该数据集包含在NetworkX一个用于Python的复杂网络包。通过使用这个包导入数据集,我们可以很容易地开始。
我使用的是NetworkX 2.2。要在Python中检查包的版本,你通常会像这样使用version package属性:
> > > networkx.__version__
MATLAB不支持金宝app类名或其他以下划线(_)字符开头的标识符.相反,请使用以下命令获取包上的帮助内容,包括其当前版本。
> py.help (“networkx”)
导入或不导入
通常,在Python脚本的开头执行此操作。
进口networkx作为nxG = nx.karate_club_graph()
但是,在MATLAB中不建议这样做,因为进口函数与Python中的函数是不同的。
调用Python的MATLAB方法是使用py,后面跟着如下的包或方法:
nxG = py.networkx.karate_club_graph();
如果你必须使用进口,你可以这样做:
进口py.networkx。*nxG = karate_club_graph();
正如您所看到的,当您省略时,很难记住我们正在调用Python方法py当您开始在同一脚本中混合MATLAB代码和Python代码时,这可能会令人困惑。
从Python对象中提取数据
下面的代码以NetworkX图对象的形式返回空手道俱乐部数据集。
myDataType = class(nxG)
myDataType = 'py.networkx.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处理a的方法列表或元组通常是这样的,在循环中处理单个元素。
为我在李:打印我#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元组也可以转换成a吗细胞数组中。来转换内部元组元素,我们可以使用cellfun.
edgeC = cellfun(@cell, edgeC,“UniformOutput”、假);myDataType = class(edgeC{1})
myDataType = 'cell'
结果嵌套细胞包含Python的数组int值。
myDataType = class(edgeC{1}{1})
myDataType = ' pyp .int'
处理Python字典
现在让我们从数据集中提取节点。我们可以按照处理边的步骤来做。
nodeL = py.list(nxG.nodes.data);nodeC = cell(nodeL);nodeC = cellfun(@cell, nodeC,“UniformOutput”、假);
一个内细胞数组包含Pythonint和dict元素。
cellContent = nodeC{1}
cellContent = 1×2细胞数组{1×1 py.int} {1×1 py.dict}
Pythondict是基于键值对的数据类型。在这种情况下,关键是“俱乐部”它的值是“你好,先生”.
cellContent = nodeC{1}{2}
cellContent =没有属性的Python字典。{'club': 'Mr. Hi'}
嗨先生是俱乐部的空手道教练。Python中的另一个值dict是“官”这位军官是俱乐部的领导人。他们是各自派系的关键人物。节点属性指示单个节点所属的派别。在这种情况下,节点1属于Hi先生的派系。
Python处理a的方法dict通常是这样的,在循环中处理单个元素。
为k、v在d.items ():Print (k, v)
同样,MATLAB的方法是使用数组。Pythondict可以转换成a吗结构体数组中。
nodeAttrs = cellfun(@(x) struct(x{2}), nodeC);myDataType = class(nodeAttrs)
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 = graph(s,t);g.s nodes .club = nodeAttrs';图P1 = plot(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.s 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)
行= 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字典。{“关键”:“价值”}
的set_node_attributes方法需要一个嵌套的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(nodeAttrs)“俱乐部”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 .algorithm .community.greedy_modularity_communities(nxG2);myDataType = class(communtiesl)
myDataType = 'py.list'
返回的蟒蛇列表包含3个元素。这意味着算法在这张图中检测到3个社区。
num_communtieis = length(communtiesl)
num_communities = 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 = ' pyp .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”) highlight(P2, communityesc {2},“NodeColor”,“# D95319”,“EdgeColor”,“# D95319”) highlight(P2, communityesc {3},“NodeColor”,“# 77 ac30”,“EdgeColor”,“# 77 ac30”)标题({“扎卡里的空手道俱乐部”,“Modularity-based社区”})
如果你比较这些图,你可以看到右边橙色和绿色的两个社区,当合并时,大致与Hi先生的派系重叠。
我们还可以看到:
- 社区1代表“军官”阵营
- 社区3代表忠诚的“嗨先生”派系
- 社区2代表了与两个派系都有联系的人
有趣的是,Community 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.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 = graph(s,t);g.s nodes .club = nodeAttrs';
要从MATLAB数据创建Python图形,您可以这样做:
nxG2 = py.networkx.Graph();edgeL = num2cell(int8(g.b edges . endnodes) - 1);nxG2.add_edges_from (py。列表(num2cell(edgeL, 2)')); attrsD = py.dict;为ii = 1:length(g.s nodes .club) attrD = pys .dict(pyargs .club)“俱乐部”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在这里.
コメント
コメントを残すには,ここをクリックしてMathWorksアカウントにサインインするか新しいMathWorksアカウントを作成します。