How to bin polar coordinates

3 views (last 30 days)
Cal White
Cal White on 24 Nov 2021
Commented: Dave B on 24 Nov 2021
I have a list of theta and a corresponding value between 0 and 1. I would like to bin all the corresponding values into bins of 1 degree.
edges = -180:1:180
X % random list of angles between -180 and 180
Y % random list of corresponding values between 0 and 1
[bins] discretize(X,edges);
yBinned = arrayfun(@(i)Y(bins==i),unique(bins),'UniformOutput', false);
This gives me an array of only 180 entries in Ybinned, which should be 360?
Any fix or alternative method for binning polar coordinates in Matlab?
Thanks

Answers (1)

Dave B
Dave B on 24 Nov 2021
Edited: Dave B on 24 Nov 2021
The way you've written the code, the number of outputs in yBinned depends on how many of the bins of X were populated.
edges = -180:1:180;
X = rand(100,1)*360-180;
Y = rand(100,1);
bins = discretize(X,edges);
yBinned = arrayfun(@(i)Y(bins==i),unique(bins),'UniformOutput', false);
size(yBinned)
ans = 1×2
85 1
numel(unique(bins))
ans = 85
If you want yBinned to correspond to the bin number, you'll need empty placeholders for cases where the bin is empty.
Method 1: somewhat wasteful, but keeps the one-liner aspect. Instead of applying the function to the populated bins (unique(bins)) apply it to the potential bins (numel(edges)-1)
yBinned = arrayfun(@(i)Y(bins==i),1:numel(edges)-1,'UniformOutput', false);
size(yBinned)
ans = 1×2
1 360
Method 2: Uses the same approach as you took to calculate the filled bins, but then distributes them into a vector. I think this is harder to read...but I suppose more efficient (I'd probably pull the unique(bins) part out if performance was really a concern).
yBinnedFull = arrayfun(@(i)Y(bins==i),unique(bins),'UniformOutput', false);
yBinned = cell(numel(edges)-1,1); % initialize in case trailing bins weren't populated
yBinned(unique(bins)) = yBinnedFull;
Note that these produce very slightly different results: method 1's empties are a 0x1 double, and method 2's empties are a 0x0 double.
  2 Comments
Cal White
Cal White on 24 Nov 2021
Thanks! Just to double check, 'Method 1' creates bins per a degree? Thanks again for the details. Is there a significant difference in 0x1 or 0x0 , I imagine 0x1 is represented with a 0 in the cell and the latter an empty cell ?
Dave B
Dave B on 24 Nov 2021
Yes - more specifically it finds the y values for each bin (and you defined bins as one bin per degree).
There's not an obvious difference between 0x0 and 0x1, they're both empty (neither one gets a 0 in the cell) and for most practical purposes they probably are the same.
But, if you're curious...in MATLAB a matrix can be empty by having no height (and any amount of width) or having no width (and any amount of height) or neither height no width (or really any dimension can be zero-sized). The difference rarely matters, and I probably just added confusion by mentioning it...but when I answer with two different methods I normally check that they produce the same result with isequal...and here they don't. Here's some more detail:
edges = -180:1:180;
rng(0); %for reproducibility
X = rand(500,1)*360-180;
Y = rand(500,1);
bins = discretize(X,edges);
a = arrayfun(@(i)Y(bins==i),1:numel(edges)-1,'UniformOutput', false);
yBinnedFull = arrayfun(@(i)Y(bins==i),unique(bins),'UniformOutput', false);
b = cell(1,numel(edges)-1); % initialize in case trailing bins weren't populated
b(unique(bins)) = yBinnedFull;
a(1:10)
ans = 1×10 cell array
{[0.6660]} {[0.2467]} {[0.0985]} {0×1 double} {[0.1476]} {2×1 double} {0×1 double} {0×1 double} {[0.7067]} {0×1 double}
b(1:10)
ans = 1×10 cell array
{[0.6660]} {[0.2467]} {[0.0985]} {0×0 double} {[0.1476]} {2×1 double} {0×0 double} {0×0 double} {[0.7067]} {0×0 double}
% demo that these are different (even though they're both empty)
a{4}
ans = 0×1 empty double column vector
b{4}
ans = []
isempty(a{4})
ans = logical
1
isempty(b{4})
ans = logical
1
% just a demo that they're the same if we look at an entry with more than one value
a{6}
ans = 2×1
0.1420 0.7819
b{6}
ans = 2×1
0.1420 0.7819
% complete comparison
ind_a = ~cellfun(@isempty,a);
ind_b = ~cellfun(@isempty,b);
isequal(ind_a,ind_b) % same set if values is empty
ans = logical
1
isequal(a(ind_a),b(ind_b)) % the non-empty values are the same
ans = logical
1

Sign in to comment.

Categories

Find more on Polar Plots in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!