es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Ordenando una matriz 2D en compartimentos y agregando pesos en cada compartimento

Supongamos que tengo una serie de coordenadas 2D (x, y), cada una correspondiente a un peso. Después de organizarlas en contenedores (es decir, un área cuadrada pequeña), quiero encontrar la suma de los pesos que caen en cada contenedor. Utilicé np.digitize para encontrar en qué contenedores caen mis datos, luego añadí pesos en cada contenedor utilizando un bucle. Mi código es así:

import numpy as np

x = np.random.uniform(low=0.0, high=10.0, size=5000) # variable x
y = np.random.uniform(low=0.0, high=10.0, size=5000) # variable y
w = np.random.uniform(low=0.0, high=10.0, size=5000) # peso en cada (x,y)

binx = np.arange(0, 10, 1)
biny = np.arange(0, 10, 1)

indx = np.digitize(x, binx)
indy = np.digitize(y, biny)

<h1>inicializar lista vacía</h1>

weight = [[0] * len(binx) for _ in range(len(biny))]

for n in range(0, len(x)):
    for i in range(0, len(binx)):
        for j in range(0, len(biny)):
            if indx[n] == binx[i] and indy[n] == biny[j]:
                weight[i][j] += w[n]

Pero la primera línea de la salida weight está vacía, lo cual no tiene sentido. ¿Por qué sucede esto? ¿Hay una forma más eficiente de lograr lo que quiero?

Edit: Tengo una buena respuesta abajo (que acepté), pero me pregunto cómo funciona si mis contenedores son flotantes. -> Ver respuesta editada

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    La razón por la cual la primera línea de la salida weight está vacía es porque estás inicializando la lista weight con [[0] * len(binx)] * len(biny), lo cual crea una lista de referencias a la misma lista interna. Entonces, cuando modificas una lista interna, estás modificando todas. Para solucionar esto, puedes usar una comprensión de listas para crear una nueva lista interna para cada elemento:

    weight = [[0] * len(binx) for _ in range(len(biny))]
    

    En cuanto a una manera más eficiente de hacer lo que deseas, puedes usar numpy.histogram2d para crear un histograma 2D que divide en intervalos las coordenadas x e y y calcula la suma de los valores correspondientes de w. Aquí tienes un ejemplo:

    import numpy as np
    
    x = np.random.uniform(low=0.0, high=10.0, size=5000) # variable x
    y = np.random.uniform(low=0.0, high=10.0, size=5000) # variable y
    w = np.random.uniform(low=0.0, high=10.0, size=5000) # peso en cada (x,y)
    
    binx = np.arange(0, 10, 1)
    biny = np.arange(0, 10, 1)
    
    H, _, _ = np.histogram2d(x, y, bins=[binx, biny], weights=w)
    
    print(H)
    

    Esto te dará un arreglo 2D H donde H[i,j] es la suma de los valores de w que caen en el intervalo (i,j). Ten en cuenta que los intervalos están definidos por los límites de los intervalos [0,1), [1,2), …, [9,10) en ambas dimensiones, por lo que (0,0) corresponde a la esquina inferior izquierda del primer intervalo. Si deseas desplazar los intervalos de manera que (0,0) corresponda al centro del primer intervalo, puedes usar binx + 0.5 y biny + 0.5 como límites de los intervalos.

Comments are closed.