Question

La dernière question que j'ai posée portait sur la manière de regrouper les données en coordonnées x. La solution était simple et élégante, et j'ai honte de ne pas l'avoir vue. Cette question peut être plus difficile (ou je peux simplement être aveugle).

J'ai commencé avec environ 140000 points de données et les ai divisés en 70 groupes équidistants sur l'axe des x. J'ai ensuite pris la position moyenne (x_avg, y_avg) de chaque groupe et les ai tracés. une belle courbe est apparue. Malheureusement, il y a deux problèmes. Premièrement, les arêtes sont beaucoup moins peuplées que le centre du graphique. Deuxièmement, certaines zones changent plus que d’autres et nécessitent donc une meilleure résolution.

J'ai donc deux questions spécifiques et une invitation générale à émettre des suggestions:

Matlab a-t-il une méthode intégrée pour diviser une matrice en un nombre fixe de petites matrices ou de petites matrices de taille fixe?

Existe-t-il un algorithme (ou une fonction matlab, mais je trouve cela improbable) pour déterminer plus précisément les limites requises pour les régions d'intérêt bin.

Plus généralement, existe-t-il un meilleur moyen de condenser des dizaines de milliers de points de données en une tendance nette?

Était-ce utile?

La solution

On dirait que vous voulez utiliser des bacs dont la taille varie en fonction de la densité des valeurs x. Je pense que vous pouvez toujours utiliser la fonction HISTC comme dans la réponse à votre précédent message, mais il vous suffirait de lui attribuer un ensemble d’arêtes différent.

Je ne sais pas si c'est exactement ce que vous voulez, mais voici une suggestion: au lieu de diviser l'axe des x en 70 groupes à égale distance, divisez les données x triées en 70 groupes égaux et déterminez les valeurs des arêtes. Je pense que ce code devrait fonctionner:

% Start by assuming x and y are vectors of data:

nBins = 70;
nValues = length(x);
[xsort,index] = sort(x);  % Sort x in ascending order
ysort = y(index);         % Sort y the same way as x
binEdges = [xsort(1:ceil(nValues/nBins):nValues) xsort(nValues)+1];

% Bin the data and get the averages as in previous post (using ysort instead of y):

[h,whichBin] = histc(xsort,binEdges);

for i = 1:nBins
    flagBinMembers = (whichBin == i);
    binMembers = ysort(flagBinMembers);
    binMean(i) = mean(binMembers);
end

Cela devrait vous donner des bacs dont la taille varie en fonction de la densité des données.

UPDATE: Une autre version ...

Voici une autre idée que j'ai suggérée après quelques commentaires. Avec ce code, vous définissez un seuil (maxDelta) pour la différence entre les points de données voisins dans x. Toutes les valeurs x qui diffèrent de leur voisin plus grand d'un montant supérieur ou égal à maxDelta sont forcées de se trouver dans leur propre compartiment (toutes par leur solitaire). Vous choisissez toujours une valeur pour nBins, mais le nombre final de bacs sera plus grand que cette valeur lorsque les points étalés sont relégués dans leurs propres bacs.

% Start by assuming x and y are vectors of data:

maxDelta = 10; % Or whatever suits your data set!
nBins = 70;
nValues = length(x);
[xsort,index] = sort(x);  % Sort x in ascending order
ysort = y(index);         % Sort y the same way as x

% Create bin edges:

edgeIndex = false(1,nValues);
edgeIndex(1:ceil(nValues/nBins):nValues) = true;
edgeIndex = edgeIndex | ([0 diff(xsort)] >= maxDelta);
nBins = sum(edgeIndex);
binEdges = [xsort(edgeIndex) xsort(nValues)+1];

% Bin the data and get the y averages:

[h,whichBin] = histc(xsort,binEdges);

for i = 1:nBins
    flagBinMembers = (whichBin == i);
    binMembers = ysort(flagBinMembers);
    binMean(i) = mean(binMembers);
end

J'ai testé cela sur quelques petits ensembles d'échantillons de données et il semble faire ce qu'il est censé faire. Espérons que cela fonctionnera également pour votre ensemble de données, quel qu’il soit! =)

Autres conseils

Je n'ai jamais utilisé matlab, mais d'après votre question précédente, je suppose que vous cherchez quelque chose du genre Kdtree ou une variante.

Clarification: Étant donné qu'il semble y avoir une certaine confusion à ce sujet, je pense qu'un exemple de pseudocode s'impose.

// Some of this shamelessly borrowed from the wikipedia article
function kdtree(points, lower_bound, upper_bound) {
    // lower_bound and upper_bound are the boundaries of your bucket
    if(points is empty) {
        return nil
    }
    // It's a trivial exercise to control the minimum size of a partition as well
    else {
        // Sort the points list and choose the median element
        select median from points.x

        node.location = median;

        node.left = kdtree(select from points where lower_bound < points.x <= median, lower_bound, median);
        node.right = kdtree(select from points where median < points.x <= upper_bound, median, upper_bound);

        return node
    }
}

kdtree(points, -inf, inf)

// or alternatively

kdtree(points, min(points.x), max(points.x))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top