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
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 listaweight
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: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 coordenadasx
ey
y calcula la suma de los valores correspondientes dew
. Aquí tienes un ejemplo:Esto te dará un arreglo 2D
H
dondeH[i,j]
es la suma de los valores dew
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 usarbinx + 0.5
ybiny + 0.5
como límites de los intervalos.