Effacer les filtres
Effacer les filtres

How to divide large data in small intervals?

4 vues (au cours des 30 derniers jours)
Anderson
Anderson le 22 Avr 2016
Commenté : Guillaume le 22 Avr 2016
How to divide a large matrix into small intervals?
For example, take the matrix [1 1; 1 2; 2 3; ...;5 100; 6 100; ...; 1 1.0e4; ...; 5 1.0e9] with many entries.
How to efficiently divide the second column into intervals of length 1, e.g. [0,1], [1,2]...[1000,1001] and so on such that, for each interval, the elements of the first column sum to 1.
Small example: M = [1 1; 2 1; 1 10; 3 10];
The output should be:
M_out = [0.333 1; 0.6667 1; 0.25 10; 0.75 10]
Take M=[1 1; 2 1; 1 1.5; 1 10; 1 10.6; 3 10];
M_out = [0.25 1; 0.5 1; 0.25 1.5; 0.20 10; 0.20 10.6; 0.6 10]
The solution could be
for i=1:1.0e9; j=find (i <= M(:,2) & M(:,2) < i+1); M(j,1) = M(j,1)./sum(M(j,1)); end
However, is it an efficiently way to do it?
  2 commentaires
Image Analyst
Image Analyst le 22 Avr 2016
Modifié(e) : Image Analyst le 22 Avr 2016
Is this your homework?
Anderson
Anderson le 22 Avr 2016
Modifié(e) : Jan le 22 Avr 2016
No.
The solution could be
for i=1:1.0e9;
j=find (i <= M(:,2) & M(:,2) < i+1);
M(j,1) = M(j,1)./sum(M(j,1));
end
However, is it an efficiently way to do it?

Connectez-vous pour commenter.

Réponse acceptée

Guillaume
Guillaume le 22 Avr 2016
Modifié(e) : Guillaume le 22 Avr 2016
It's not very clear from your question that you want to bin the second column in bins of width 1, and you haven't given a criteria for the bin edges. Should the edges always be integer?
Anyway, find out which bin your second column falls into with discretize and use these bins as input to accumarray as per Star's or the cyclist's answer:
M = [1 1; 2 1; 1 1.5; 1 10; 1 10.6; 3 10];
%compute bins. Assume integer edges
binlow = floor(min(M(:, 2)));
binhigh = ceil(max(M(:, 2)));
if binhigh == max(M(:, 2)), binhigh = binhigh + 1; end %otherwise if max is integer it'll be included in the previous bin
binidx = discretize(M(:, 2), binlow : binhigh);
%apply to accumarray
binsum = accumarray(binidx, M(:, 1));
%normalise
M_out = [M(:, 1) ./ binsum(binidx), M(:, 2)]
  2 commentaires
Anderson
Anderson le 22 Avr 2016
Modifié(e) : Anderson le 22 Avr 2016
Thank you for your reply.
Yes, the edges are integer and the range is large: from 0 to 1.0e9.
Is there a way to not use discretize function? This function is not available for previous MATLAB versions.
Guillaume
Guillaume le 22 Avr 2016
If you're not using up to date matlab, please mention it in your question.
Any histogram function will do, the second return value of histc will work. Since histc behaves differently for the last edge, the code becomes:
binlow = floor(min(M(:, 2)));
binhigh = ceil(max(M(:, 2))) + 1; %always add an extra bin
[~, binidx] = histc(M(:, 2), binlow:binhigh);
%accumarray code as before

Connectez-vous pour commenter.

Plus de réponses (1)

the cyclist
the cyclist le 22 Avr 2016
Modifié(e) : the cyclist le 22 Avr 2016
M = [1 1; 2 1; 1 10; 3 10];
[~,~,idx] = unique(M(:,2));
S = accumarray(idx,M(:,1),[]);
M_out = [M(:,1)./S(idx),M(:,2)]
  1 commentaire
Anderson
Anderson le 22 Avr 2016
This solution does not divide the second column into intervals of length 1.
Take M=[1 1; 2 1; 1 1.5; 1 10; 1 10.6; 3 10];
M_out = [0.25 1; 0.5 1; 0.25 1.5; 0.20 10; 0.20 10.6; 0.6 10]

Connectez-vous pour commenter.

Catégories

En savoir plus sur Numeric Types dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by