python - tutorial - numpy zeros
Python cómo rellenar una matriz numpy con ceros (4)
En caso de que necesite agregar una cerca de 1s a una matriz:
>>> mat = np.zeros((4,4), np.int32)
>>> mat
array([[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]])
>>> mat[0,:] = mat[:,0] = mat[:,-1] = mat[-1,:] = 1
>>> mat
array([[1, 1, 1, 1],
[1, 0, 0, 1],
[1, 0, 0, 1],
[1, 1, 1, 1]])
Quiero saber cómo puedo rellenar una matriz numpy 2D con ceros usando python 2.6.6 con la versión numpy 1.5.0.
¡Lo siento!
Pero estas son mis limitaciones.
Por lo tanto, no puedo usar
np.pad
.
Por ejemplo, quiero rellenar
a
con ceros de modo que su forma coincida con
b
.
La razón por la que quiero hacer esto es para poder hacer:
b-a
tal que
>>> a
array([[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.]])
>>> b
array([[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.]])
>>> c
array([[1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0]])
La única forma en que puedo pensar en hacer esto es anexar, sin embargo, esto parece bastante feo.
¿Existe una solución más limpia que posiblemente use
b.shape
?
Editar, gracias a la respuesta de MSeiferts. Tuve que limpiarlo un poco, y esto es lo que obtuve:
def pad(array, reference_shape, offsets):
"""
array: Array to be padded
reference_shape: tuple of size of ndarray to create
offsets: list of offsets (number of elements must be equal to the dimension of the array)
will throw a ValueError if offsets is too big and the reference_shape cannot handle the offsets
"""
# Create an array of zeros with the reference shape
result = np.zeros(reference_shape)
# Create a list of slices from offset to offset + shape in each dimension
insertHere = [slice(offsets[dim], offsets[dim] + array.shape[dim]) for dim in range(array.ndim)]
# Insert the array in the result at the specified offsets
result[insertHere] = array
return result
Entiendo que su principal problema es que necesita calcular
d=ba
pero sus matrices tienen diferentes tamaños.
No hay necesidad de un acolchado intermedio
c
Puede resolver esto sin relleno:
import numpy as np
a = np.array([[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.]])
b = np.array([[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.],
[ 3., 3., 3., 3., 3., 3.]])
d = b.copy()
d[:a.shape[0],:a.shape[1]] -= a
print d
Salida:
[[ 2. 2. 2. 2. 2. 3.]
[ 2. 2. 2. 2. 2. 3.]
[ 2. 2. 2. 2. 2. 3.]
[ 3. 3. 3. 3. 3. 3.]]
Muy simple, crea una matriz que contiene ceros utilizando la forma de referencia:
result = np.zeros(b.shape)
# actually you can also use result = np.zeros_like(b)
# but that also copies the dtype not only the shape
y luego inserte la matriz donde la necesite:
result[:a.shape[0],:a.shape[1]] = a
y listo lo has rellenado:
print(result)
array([[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
También puede hacerlo un poco más general si define dónde se debe insertar su elemento superior izquierdo
result = np.zeros_like(b)
x_offset = 1 # 0 would be what you wanted
y_offset = 1 # 0 in your case
result[x_offset:a.shape[0]+x_offset,y_offset:a.shape[1]+y_offset] = a
result
array([[ 0., 0., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 1., 1.],
[ 0., 1., 1., 1., 1., 1.],
[ 0., 1., 1., 1., 1., 1.]])
pero luego tenga cuidado de no tener compensaciones más grandes de lo permitido.
Para
x_offset = 2
por ejemplo, esto fallará.
Si tiene un número arbitrario de dimensiones, puede definir una lista de sectores para insertar la matriz original. Me pareció interesante jugar un poco y creé una función de relleno que puede rellenar (con desplazamiento) una matriz de forma arbitraria siempre que la matriz y la referencia tengan el mismo número de dimensiones y los desplazamientos no sean demasiado grandes.
def pad(array, reference, offsets):
"""
array: Array to be padded
reference: Reference array with the desired shape
offsets: list of offsets (number of elements must be equal to the dimension of the array)
"""
# Create an array of zeros with the reference shape
result = np.zeros(reference.shape)
# Create a list of slices from offset to offset + shape in each dimension
insertHere = [slice(offset[dim], offset[dim] + array.shape[dim]) for dim in range(a.ndim)]
# Insert the array in the result at the specified offsets
result[insertHere] = a
return result
Y algunos casos de prueba:
import numpy as np
# 1 Dimension
a = np.ones(2)
b = np.ones(5)
offset = [3]
pad(a, b, offset)
# 3 Dimensions
a = np.ones((3,3,3))
b = np.ones((5,4,3))
offset = [1,0,0]
pad(a, b, offset)
NumPy 1.7.0 (cuando se agregó
numpy.pad
) es bastante antiguo ahora (se lanzó en 2013), así que aunque la pregunta solicitó una forma
sin usar
esa función, pensé que podría ser útil saber cómo se podría lograr eso usando
numpy.pad
.
En realidad es bastante simple:
>>> import numpy as np
>>> a = np.array([[ 1., 1., 1., 1., 1.],
... [ 1., 1., 1., 1., 1.],
... [ 1., 1., 1., 1., 1.]])
>>> np.pad(a, [(0, 1), (0, 1)], mode=''constant'')
array([[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
En este caso, utilicé que
0
es el valor predeterminado para
mode=''constant''
.
Pero también podría especificarse pasándolo explícitamente:
>>> np.pad(a, [(0, 1), (0, 1)], mode=''constant'', constant_values=0)
array([[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
En caso de que el segundo argumento (
[(0, 1), (0, 1)]
) parezca confuso: cada elemento de la lista (en este caso, la tupla) corresponde a una dimensión y el elemento en él representa el relleno
antes
(primer elemento) y
después
(segundo elemento).
Entonces:
[(0, 1), (0, 1)]
^^^^^^------ padding for second dimension
^^^^^^-------------- padding for first dimension
^------------------ no padding at the beginning of the first axis
^--------------- pad with one "value" at the end of the first axis.
En este caso, el relleno para el primer y el segundo eje son idénticos, por lo que también se podría pasar la tupla de 2:
>>> np.pad(a, (0, 1), mode=''constant'')
array([[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
En caso de que el relleno antes y después sea idéntico, incluso podría omitirse la tupla (aunque no es aplicable en este caso):
>>> np.pad(a, 1, mode=''constant'')
array([[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0., 0.]])
O si el relleno antes y después es idéntico pero diferente para el eje, también puede omitir el segundo argumento en las tuplas internas:
>>> np.pad(a, [(1, ), (2, )], mode=''constant'')
array([[ 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
Sin embargo, tiendo a preferir usar siempre el explícito, porque es muy fácil cometer errores (cuando las expectativas de NumPys difieren de sus intenciones):
>>> np.pad(a, [1, 2], mode=''constant'')
array([[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 1., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.]])
¡Aquí NumPy cree que quería rellenar todos los ejes con 1 elemento antes y 2 elementos después de cada eje! Incluso si pretendía rellenar con 1 elemento en el eje 1 y 2 elementos para el eje 2.
Usé listas de tuplas para el relleno, tenga en cuenta que esto es solo "mi convención", también podría usar listas de listas o tuplas de tuplas, o incluso tuplas de matrices. ¡NumPy solo comprueba la longitud del argumento (o si no tiene una longitud) y la longitud de cada elemento (o si tiene una longitud)!