使用treeplot在MATLAB中绘制嵌套单元格树形图。

4

我有一个表示树形结构的复杂单元格:

CellArray = {1,1,1,{1,1,1,{1,1,{1,{1 1 1 1 1 1 1 1}, 1,1}, 1,1},1,1,1},1,1,1,{1,1,1,1}};

我想通过使用treeplot(p)绘制相关树形结构,但不确定如何构建数组p以正确显示。


1
你能否发布一下你目前尝试过的内容?或者你遇到了哪些问题? - crazyGamer
2
相关链接:https://stackoverflow.com/questions/45665684/finding-number-of-all-nested-cells-in-a-complex-cell - Wolfie
1个回答

9
我们可以创建一个递归函数,探索您的单元格数组,并创建树指针数组(如文档中所述)到每个节点的父节点。
此函数接受一个单元格数组(例如您问题中的数组),该数组包含标量或嵌套的单元格数组。
treebuilder 的逻辑:
  1. 如果一个项目是标量值,则分配一个父节点编号,增加节点数量 1。
  2. 如果一个项目是单元格数组,则在该单元格上运行treebuilder函数,返回已达到的最大节点编号(以及生成的子树)。
  3. 由于步骤2,函数是递归的,因此重复直到处理完每个元素。

函数:

function treearray = getTreeArray(cellarray)
    % initialise the array construction from node 0
    treearray = [0, treebuilder(cellarray, 1)]; 
    % recursive tree building function, pass it a cell array and root node
    function [out, node] = treebuilder(cellarray, rnode)
        % Set up variables to be populated whilst looping
        out = []; 
        % Start node off at root node
        node = rnode;
        % Loop over cell array elements, either recurse or add node
        for ii = 1:numel(cellarray)
            tb = []; node = node + 1;
            if iscell(cellarray{ii})
                [tb, node] = treebuilder(cellarray{ii}, node);
            end
            out = [out, rnode, tb];   
        end
    end
end

简单示例的使用方法

这是一个比你的更简单的示例,因此我们可以轻松地检查逻辑是否有效。

myCellArray = {1 1 {1 1 1 {1 1 1}}};
% This cell array has 3 levels: 
% - 3 child nodes (2,3,4) of the root node (1) 
% - Last node on the first level (4) has 4 children:
%     - 4 child nodes on second level (5,6,7,8) 
%     - Last node on the first level (8) has 3 children:
%         - 3 child nodes on third level (9,10,11)
myTreeArray = getTreeArray(myCellArray);
% Output, we see the corresponding nodes as listed above:
% [0 1 1 1 4 4 4 4 8 8 8]
treeplot(myTreeArray)

simple


你的单元数组

我认为这个按预期工作,注意你不必定义myCellArraymyTreeArray变量:

treeplot(getTreeArray({1,1,1,{1,1,1,{1,1,{1,{1 1 1 1 1 1 1 1}, 1,1}, 1,1},1,1,1},1,1,1,{1,1,1,1}}))

这里是输出图像,显示算法可以处理更复杂的树形结构。速度似乎也不错,但展示极其复杂的树形结构会有些多余!

编辑:标记节点

您可以通过使用treelayout获取节点位置并在构建树状数组时遇到值时进行跟踪来标记节点。应调整函数以实现此“跟踪”操作,如下所示:
function [treearray, nodevals] = getTreeArray(cellarray)
    % initialise the array construction from node 0
    [nodes, ~, nodevals] = treebuilder(cellarray, 1); 
    treearray = [0, nodes];
    % recursive tree building function, pass it a cell array and root node
    function [out, node, nodevals] = treebuilder(cellarray, rnode)
        % Set up variables to be populated whilst looping
        out = []; nodevals = {};
        % Start node off at root node
        node = rnode;
        % Loop over cell array elements, either recurse or add node
        for ii = 1:numel(cellarray)
            node = node + 1;
            if iscell(cellarray{ii})
                [tb, node, nv] = treebuilder(cellarray{ii}, node);
                out = [out, rnode, tb];  
                nodevals = [nodevals, nv];
            else
                out = [out, rnode];
                nodevals = [nodevals, {node; cellarray{ii}}];
            end 
        end
    end
end
注意: 如果您想在图上标号,则可以使用类似的适应性来跟踪节点编号而不是节点
在这里,我使用了一个单元数组,以便每个节点上都可以有文本或数字值。如果您只需要数字值,则可以将nodevals存储在矩阵中,这样可以缩短后期格式化的时间。
然后,要绘制这个图,请使用:
% Run the tree building script above
[treearray, nodevals] = getTreeArray(myCellArray);
% Plot
treeplot(treearray);
% Get the position of each node on the plot  
[x,y] = treelayout(treearray);
% Get the indices of the nodes which have values stored
nodeidx = cell2mat(nodevals(1,:));
% Get the labels (values) corresponding to those nodes. Must be strings in cell array
labels = cellfun(@num2str, nodevals(2,:), 'uniformoutput', 0);
% Add labels, with a vertical offset to the y coords so that labels don't sit on nodes
text(x(nodeidx), y(nodeidx) - 0.03, labels);

下面是单元格myCellArray = {{17, 99.9}, 50}的示例输出,我选择这些数字是为了明确它们不是实际的“节点编号”!

输入图像描述


工作得非常完美!感谢您的解释和注释行。 - Zander
1
非常感谢您分享宝贵的知识 :) - Zander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接