How to plot data from cell array based on a logical array?

12 次查看(过去 30 天)
I started with the manual code below to plot five lines of data:
% code
xAxis = 1:numel(plotLine1);
myPlot = plot(xAxis,plotLine1(:)','k',...
xAxis,plotLine2(:)','b',...
xAxis,plotLine3(:)','c',...
xAxis,plotLine4(:)','m',...
xAxis,plotLine5(:)','g','LineWidth', 0.5)
But I want to select which data to plot based on a function output. The function populates the data into plotLine(n) and also returns a "logical" 1x5 cell array (1 for "yes", 0 for "no"), which is used to select, from plotData, which lines of data will be plotted. The logical array can contain any possible combination of the five data sets. Since each data has its own color defined, plotLine1 will always contains the data Ch01, plotLine2 the Ch06 and so on. Then I use plotData with the "logical" array to find out which data will be plotted.
% code
plotData(1,1) = {'xAxis,plotLine1(:),''k'''};
plotData(1,2) = {'xAxis,plotLine2(:),''b'''};
plotData(1,3) = {'xAxis,plotLine3(:),''c'''};
plotData(1,4) = {'xAxis,plotLine4(:),''g'''};
plotData(1,5) = {'xAxis,plotLine5(:),''m'''};
ri = 1;
for r=1:5
a=logicArray(1,r);
bitTest = str2num(a{:});
switch bitTest
case 1
plotContents(1,ri) = {plotData(1,r)};
ri = ri + 1;
end
end
plotData only holds the references to the data (plotLine = 18000x40 double, that is loaded with the necessary data in the function).
I have tried concatenating plotContents:
% code
toPlot = '';
for r = 1:numel(plotContents)
if r < numel(plotContents)
toPlot = strcat(toPlot,plotContents{1,r},',');
else
toPlot = strcat(toPlot,plotContents{1,r});
end
end
finalPlot = toPlot{:};
myPlot = plot(finalPlot,'LineWidth', 0.5)
But it gives the error: "Error using plot Invalid first data argument.
Error in PlotViewer_function (line 234) myPlot = plot(finalPlot,'LineWidth', 0.5)"
I have also tried:
% code
hold on
cellfun(@(x) plot(x), plotContents);
Error code: "Error using plot Invalid first data argument
Error in PlotViewer_function>@(x)plot(x) (line 233) cellfun(@(x) plot(x), plotContents);"
I have also tried:
% code
finalPlot = strcat(toPlot{:},',''LineWidth'', 0.5');
myPlot = plot(finalPlot)
where finalPlot is a 1x85 char containing (in one example): xAxis,plotLine1(:),'k',xAxis,plotLine3(:),'c',xAxis,plotLine5(:),'m','LineWidth', 0.5
The error it gives: "Error using plot Invalid first data argument.
Error in PlotViewer_function (line 236) myPlot = plot(finalPlot) "
How can I plot the selected data using plotLine(n) and the logical array?

采纳的回答

Stephen23
Stephen23 2018-11-12
编辑:Stephen23 2018-11-13
Far too complex.
You are trying to define strings which will be magically evaluated and converted back into data. The syntax you invented (passing character vectors/strings to the plot function) simply does not work. Did you see this in the plot documentation? This could be made to work, but it would be a very slow, complex, obfuscated, and buggy way to write code. Read this to know why:
You also throw away most of your strings here anyway:
finalPlot = toPlot{:};
Method One: comma-separate list: there is no reason why you need to use strings at all. Why bother? Just put all of the numeric data into a cell array and then use a comma-separated list when calling plot. First lets define some sample data:
>> N = 7;
>> Y = randi(9,N,5)
Y =
8 7 8 2 5
5 2 7 8 2
6 3 9 9 9
4 9 6 9 8
3 8 1 7 9
2 7 4 4 1
3 6 1 4 5
>> X = linspace(0,1,N);
and then select which data to plot using the logical index idx:
C = num2cell(Y,1);
C = repmat(C,3,1);
C(1,:) = {X};
C(3,:) = {'k','b','c','g','m'};
idx = [true,true,false,false,true];
plot(C{:,idx}) % comma-separated list
Method two: basic indexing: here is an another solution using basic MATLAB indexing and NaN's (which are not plotted). The same columns will always have the same color, regardless of which columns you plot.
>> plot(X(:),Y+(0./idx))
>> legend('L1','L2','L3','L4','L5')
Just change the index vector and you will get only those columns that you request:
>> idx = [false,true,false,true,false];
>> plot(X(:),Y+(0./idx))
>> legend('L1','L2','L3','L4','L5')
To make this work for your situation just need to concatenate those vectors into one matrix (which they should be already):
Y = [plotLine1(:),plotLine2(:),plotLine3(:),plotLine4(:),plotLine5(:)];
and define the index something like this (not that str2num is best avoided):
idx = str2double(a)==1;
You can change the color by setting the axes' line ColorOrder property.
  3 个评论
Stephen23
Stephen23 2018-11-13
编辑:Stephen23 2018-11-13
"I was trying to adapt your second method "plot(X(:),Y+(0./idx))" to my data, but I got the error:"
Error using +
Matrix dimensions must agree.
This depends on what MATLAB version you are using. The code I gave required R2016b or later, which includes the changes introduced here:
For earlier MATLAB versions you will need to replace the + with bsxfun and plus:
bsxfun(@plus,Y,0./idx)
or create an appropriately-sized logical matrix (e.g. using repmat) and use that.

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Data Type Identification 的更多信息

产品


版本

R2015a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by