Pregunta

La última pregunta que hice se refería a cómo agrupar datos por x coordenadas. La solución fue simple y elegante, y me da vergüenza no haberla visto. Esta pregunta puede ser más difícil (o simplemente puedo estar ciego).

Comencé con aproximadamente 140000 puntos de datos y los dividí en 70 grupos igualmente espaciados a lo largo del eje x. Luego tomé la posición promedio (x_avg, y_avg) de cada grupo y los graficé; apareció una bonita curva. Lamentablemente hay dos problemas. En primer lugar, los bordes están mucho menos poblados que el centro del gráfico; En segundo lugar, algunas áreas cambian más que otras y, por lo tanto, necesitan una mejor resolución.

Por lo tanto, tengo dos preguntas específicas y una invitación general para lanzar sugerencias:

¿Matlab tiene una forma integrada de dividir una matriz en un número fijo de matrices más pequeñas o matrices más pequeñas de un tamaño fijo?

¿Existe un algoritmo (o una función matlab, pero creo que es poco probable) para determinar los límites requeridos para agrupar regiones de interés más finamente?

En términos más generales, ¿hay una mejor manera de condensar decenas de miles de puntos de datos en una tendencia ordenada?

¿Fue útil?

Solución

Parece que quiere usar contenedores que varían en tamaño dependiendo de la densidad de los valores de x. Creo que todavía puedes usar la función HISTC como en la respuesta a tu publicación anterior, pero solo deberías darle un conjunto diferente de bordes.

No sé si esto es exactamente lo que quiere, pero aquí hay una sugerencia: en lugar de dividir el eje x en 70 grupos espaciados por igual, divida los datos x ordenados en 70 grupos iguales y determine los valores de los bordes. Creo que este código debería funcionar:

% 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

Esto debería darle contenedores que varían en tamaño con la densidad de datos.


ACTUALIZACIÓN: Otra versión ...

Aquí hay otra idea que se me ocurrió después de algunos comentarios. Con este código, establece un umbral (maxDelta) para la diferencia entre los puntos de datos vecinos en x. Cualquier valor de x que difiera de su vecino más grande en una cantidad mayor o igual a maxDelta se ve obligado a estar en su propio contenedor (todo por su solitario). Todavía elige un valor para nBins, pero el número final de bins será mayor que este valor cuando los puntos desplegados se releguen a sus propios bins.

% 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

Probé esto en algunos pequeños conjuntos de datos de muestra y parece hacer lo que se supone que debe hacer. ¡Esperemos que también funcione para su conjunto de datos, lo que sea que contenga! =)

Otros consejos

Nunca he usado matlab, pero al mirar su pregunta anterior sospecho que está buscando algo similar a un Kdtree o una variación.

Aclaración: Dado que parece haber cierta confusión al respecto, creo que es necesario un ejemplo de pseudocódigo.

// 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))
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top