automate scatter markers colours in groups

5 ビュー (過去 30 日間)
Jason
Jason 2025 年 3 月 13 日
コメント済み: Jason 2025 年 3 月 14 日
Hello, I have a line plot with 28 points, and I want to colour the points in groups of 2, so points 1,2, 3,4, 5,6
I started with this
ax=app.UIAxes4;
[x,y] = getDataFromGraph(app,ax,1); % Get x,y, data from plot
hold(ax,'on');
n=numel(x); % Typically 28, but want to allow for any (even number)
Groups=2; % Want to allow for 2,3,4 or 5
% the number of point sis always a multiple of Groups
% I started to manually write c, but its too tediuos
c = [ 0 0 1; 0 0 1; 0 1 0; 0 1 0; 0 1 1; 0 1 1; 1 0 0; 1 0 0; 0 1 0; 1 0 0; 1 0 1; 0 1 1; 0 0 1; 0 1 0; 0 0 1; 0 1 0; 1 0 0; 1 0 1; 0 1 1; 0 0 1; 0 1 0; 0 0 1; 0 1 0; 1 0 0; 1 0 1; 0 1 1; 0 0 1; 0 1 0];
scatter(ax,x,y, [], c, 'filled')
Can 'c' be automated?
(You can see the first 6 points below)
Thanks

採用された回答

dpb
dpb 2025 年 3 月 13 日
編集済み: dpb 2025 年 3 月 13 日
Alternate way to define the c vector index for lookup and using a colormap...
x=1:12; y=rand(size(x)); % make up some data...
N=numel(x); % the number of datapoints
G=2; % the groups
P=N/G; % passes -- is assumed N evenly divisible by G; should error check
ic=kron(1:N/G,ones(1,G)).'; % create index vector into COLORS array
colormap('hot')
scatter(x,y,[],ic,'filled')
indexes into the chosen colormap by the number of groups specified...
If you want specific colors, then create them as RGB triplets for your own colormap or use index into the array row with the indexing variable as
scatter(x,y,[],COLORS(ic,:),'filled')
where COLORS is your specific color RGB array you define.
  6 件のコメント
dpb
dpb 2025 年 3 月 13 日
編集済み: dpb 2025 年 3 月 13 日
To do it that way, you need to remap the index lookup to the size of the map...
myMap=[
0.47 0.25 0.80; % Color 1
0.83 0.14 0.14; % Color 2
0.25 0.80 0.54; % Color 3
1.00 0.54 0.00; % Color 4
0.3960 0.5090 0.9920; % Color 5
1 0 1; % Color 6
0.2270 0.7840 0.1920; % Color 7
1.0000 0.2700 0.2270]; % Color 8
N=26; G=2;
x=1:N; y=x.^2;
ic=kron(1:N/G,ones(1,G)).';
M=height(myMap); % will be 8 above
icc=mod(ic,M); icc(icc==0)=M; % remap to repeat range 1:M
Then, scatter using
scatter(x,y,[],myMap(icc,:),'filled')
will produce the sets of two (G) in sequence.
BTW, the MATLAB idiom to do the above (even though not needed here) would be
myMap=repmat(myMap,8,1); % expand to 8x original height
height(myMap)
ans = 64
Jason
Jason 2025 年 3 月 13 日
Thanks

サインインしてコメントする。

その他の回答 (4 件)

dpb
dpb 2025 年 3 月 13 日
You need to either predefine n/Groups colors if you want them to be specific colors or you can use a linear index into a color map by group.
Then set the color as a lookup by the indexing expression based on Groups. An alternative and probably simpler coding solution would be to use hold on and multiple calls to scatter in a for...end loop; that way the color for the group is the same and just based on the index of the loop...
ax=app.UIAxes4;
[x,y] = getDataFromGraph(app,ax,1); % Get x,y, data from plot
hold(ax,'on');
n=numel(x); % Typically 28, but want to allow for any (even number)
Groups=2; % Want to allow for 2,3,4 or 5
COLORS='brgckmy'; % the standard letter mnemonics can handle up to seven groups - or build custom
% the number of point sis always a multiple of Groups
passes=n/Groups; % how many groups there are in the dataset to do...
hS=gobjects(passes,1); % preallocate for scatter handles so can modify later if desired...
i1=1; % the first index to first group
for ix=1:passes
i2=i1+Groups-1; % the second index in group based on first and size chosen
hS(ix)=scatter(ax,x(i1:i2),y(i1:i2), [], COLORS(ix), 'filled'); % and plot the points
i1=i2+1; % update the first index for next pass
end
Salt to suit...

Voss
Voss 2025 年 3 月 13 日
"Can 'c' be automated?"
Here is one way to automatically construct an n-by-3 matrix c with groups of repeated rows (colors), which you can use in scatter.
% somedata and axes to plot on
ax = gca();
x = 1:28;
y = 2*x.^2-5*x+3;
n = numel(x); % Typically 28, but want to allow for any (even number)
Groups = 3; % Want to allow for 2,3,4 or 5
number_of_groups = ceil(n/Groups);
% some set of colors to use
colors = get(ax,'ColorOrder');
n_colors = size(colors,1);
% replicate the colors so there are enough for each group of points
colors = repmat(colors,ceil(number_of_groups/n_colors),1);
% construct c by appropriate indexing into the rows of colors
idx = repelem(1:number_of_groups,1,Groups);
idx = idx(1:n);
c = colors(idx,:)
c = 28×3
0 0.4470 0.7410 0 0.4470 0.7410 0 0.4470 0.7410 0.8500 0.3250 0.0980 0.8500 0.3250 0.0980 0.8500 0.3250 0.0980 0.9290 0.6940 0.1250 0.9290 0.6940 0.1250 0.9290 0.6940 0.1250 0.4940 0.1840 0.5560
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
% make the scatter plot
scatter(ax,x,y, [], c, 'filled')
  1 件のコメント
Jason
Jason 2025 年 3 月 13 日
thankyou

サインインしてコメントする。


Image Analyst
Image Analyst 2025 年 3 月 13 日
There is a function for exactly that, which makes it easy to color markers by group. It's called gscatter
help gscatter
gscatter - Scatter plot by group This MATLAB function creates a scatter plot of x and y, grouped by g. Syntax gscatter(x,y,g) gscatter(x,y,g,clr,sym,siz) gscatter(x,y,g,clr,sym,siz,doleg) gscatter(x,y,g,clr,sym,siz,doleg,xnam,ynam) gscatter(ax,___) gscatter(___,"filled") h = gscatter(___) Input Arguments x - x-axis values numeric vector y - y-axis values numeric vector g - Grouping variable categorical vector | logical vector | numeric vector | character array | string array | cell array of character vectors | cell array clr - Marker colors MATLAB default colors (default) | character vector or string scalar of short color names | matrix of RGB triplets sym - Marker symbols '.' (default) | character vector or string scalar of symbols siz - Marker sizes positive numeric vector doleg - Option to include legend 'on' (default) | 'off' xnam - x-axis label x variable name (default) | character vector | string scalar ynam - y-axis label y variable name (default) | character vector | string scalar "filled" - Option to fill interior of markers "filled" ax - Axes for plot Axes object | UIAxes object Output Arguments h - Graphics handles array of Line objects Examples openExample('stats/ScatterPlotWithDefaultSettingsExample') openExample('stats/ScatterPlotOfClimateAndHousingRatingsExample') openExample('stats/ScatterPlotWithMultipleGroupingVariablesAndAllOptionsExample') openExample('stats/SpecifyAxesForScatterPlotExample') openExample('stats/SpecifyMarkerColorsExample') openExample('stats/ModifyScatterPlotAfterCreationExample') See also gplotmatrix, grpstats, scatter Introduced in Statistics and Machine Learning Toolbox before R2006a Documentation for gscatter doc gscatter
  2 件のコメント
Jason
Jason 2025 年 3 月 13 日
OK thanks, I've taken a look - its not easy to follow for my case.
I used this:
clr = hsv(G); % G = 2
gscatter(ax,x,y,clr)
But it needs 'idx' what ever that is.
dpb
dpb 2025 年 3 月 13 日
gscatter(x,y,g,clr,sym,siz,doleg,xnam,ynam)
I had forgotten there is gscatter, indeed. It has to have the grouping variable as the third argument; that could be the ic indexing vector.

サインインしてコメントする。


Jason
Jason 2025 年 3 月 13 日
編集済み: Jason 2025 年 3 月 13 日
Perhaps I should start a new question, apologies if I should.
The data I showed in groups of 2 has the same measurement in pairs, i.e. 1& 2 measure the same thing, 3&4 etc. I am picking up vibrations which is causing the "trianglular" spikes, so I just take the lowest value of each pair
I have just manually been removing them (the orange curve) and trying to perform smoothing or poly fit (white dashed curve)to whats left.
It would be useful to automate these removals, I have tried rmoutliers (SGolay) but it didn't touch them
Any ideas how to remove them, and ideas for more of a flat bottomed function to perform the fit (rather than the poly 4 fit)?
Howabout removing the peak in the orange curve at x=6?
Thanks
  2 件のコメント
Voss
Voss 2025 年 3 月 13 日
Here's a way to programmatically determine the lower of each pair and remove those rows. (In case of an odd initial number of rows, so that one row is unpaired, the unpaired row is preserved.)
data = readmatrix('PairedData.txt');
N = size(data,1);
if mod(N,2)
data(end+1,:) = NaN;
N = N+1;
end
[~,idx] = min(reshape(data(:,2),2,[]),[],1);
rows_to_keep = 2*(0:N/2-1)+idx;
data_keep = data(rows_to_keep,:);
plot(data(:,1),data(:,2),'s-')
hold on
plot(data_keep(:,1),data_keep(:,2),'x-')
Jason
Jason 2025 年 3 月 14 日
Thankyou

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeGraphics Object Programming についてさらに検索

タグ

製品


リリース

R2023b

Community Treasure Hunt

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

Start Hunting!

Translated by