Problema al eliminar elementos de un array: “cannot delete array elements”

publicado por: Anonymous

Tengo un problema al que no le encuentro solución por más vueltas que le doy. Tengo un programa en el que genero una serie de datos y los almaceno en una lista. Más adelante tengo que eliminar algunos de los elementos de la lista para que su tamaño sea más pequeño. Siempre elimino el primer o último elemento de la lista para lo que utilizo las funciones “del” o “pop”.

Para generar la lista sobre la que quiero trabajar, llamo a una función creada por mí y que devuelve una lista. Algo así:

y = generadatos(a1,a2,a3)
del y[0]

Cuando llega a la línea con el “del” se cuelga el programa.
He probado a hacerlo desde la consola escribiendo
del y[0]
y me da el siguiente error:

ValueError: cannot delete array elements

Sin embargo si abro una hoja nueva y creo este sencillo código funciona sin problemas:

a=[1,2,3,4]
del a[0]

print a

Si en lugar de usar “del” uso “pop” sucede lo mismo. He pensado que quizá la lista que me devuelve la función que genera los datos hace algo que no entiendo y por eso no me deja borrar elementos.

¿Alguna idea?

Muchas gracias.

Edit1:

La función “generadatos” es esta:

def generadatos(nst,p0st,ast,lbst,timesstrst,pvst,incremst):
xbigst = 0
xsmallst = 0

I0bigst = []
I0smallst = []

for ist in range(0,nst+1):
    pst = p0st + ast*ist

    pbigst = np.abs((pst*pvst)/(pst-pvst))
    psmallst = np.abs((pst*pvst)/(pst+pvst))

    limitpbigst = pbigst/lbst          
    limitpbigst = np.int(limitpbigst)
    halflimitpbigst = np.int(limitpbigst/2)

    limitpsmallst = psmallst/lbst          
    limitpsmallst = np.int(limitpsmallst)
    halflimitpsmallst = np.int(limitpsmallst/2)

    for jst in range(0,timesstrst):
        for kst in range(0,halflimitpbigst):
            I0bigst.append(1)
            xbigst = xbigst + 1

        for lst in range(halflimitpbigst,limitpbigst):
            I0bigst.append(0)
            xbigst = xbigst + 1

        for mst in range(0,halflimitpsmallst):
            I0smallst.append(1)
            xsmallst = xsmallst + 1

        for ost in range(halflimitpsmallst,limitpsmallst):
            I0smallst.append(0)
            xsmallst = xsmallst + 1            

limitpbig2st = np.int((pbigst/2)/lbst)
for qst in range (0,limitpbig2st):
    del I0bigst[-1]

limitpsmall2st = np.int((psmallst/2)/lbst)
for rst in range (0,limitpsmall2st):
    del I0smallst[-1]

if incremst > 0:
    aux1st = I0bigst[::]
    I0bigst = aux1st[::-1]
else:
    aux1st = I0smallst[::]
    I0smallst = aux1st[::-1]

I0st = np.append(I0smallst,I0bigst)

return I0st`

Al principio creo listas vacias al estilo I0 = [].
Después le añado datos usando `I0.append(valor)
Y al final uso la función de NumPy
I0st = np.append(I0smallst,I0bigst)

return I0st

solución

Los arrays de NumPy no son redimensionables ni tampoco permiten el tipado dinámico. Esto es así porque se busca eficiencia, usando código compilado de C por debajo de la forma más directa posible. Esto implica que redimensionar un array implica si o si crear un nuevo array. Esta es la causa por la que del no funciona.

Hay dos formas de eliminar elementos de un array de NumPy, ambos implican crear una copia del array y es esta copia la que se retorna (porque como se ha comentado no se pude hacer inplace):

РUsar el m̩todo numpy.delete

    >>> import numpy as np

    # Eliminar el primer elemento:
    >>> a = np.array([1, 2, 3, 4])
    >>> a = np.delete(a, 0)
    >>> a
    array([2, 3, 4])

    # Eliminar el último elemento
    >>> a = np.array([1, 2, 3, 4])
    >>> a = np.delete(a, a.shape[0] - 1)
    >>> a
    array([1, 2, 3])

    # Eliminar el primero y el último:

    >>> a = np.array([1, 2, 3, 4])
    >>> a = np.delete(a, (0, a.shape[0] - 1))
    >>> a
    array([2, 3])

Recibe tres parámetros:

  1. El array como primer argumento.

  2. El indice (o iterable con los índices) del o de los elementos a eliminar como segundo argumento.

  3. El eje sobre el que se actúa como tercero.

Nota: En un futuro (según los propios desarrolladores) np.delete permitirá el uso de indices negativos, por lo que podremos cambiar a = np.delete(a, a.shape[0] - 1) por a = np.delete(a,- 1).

– Usar técnicas de rebanado (slicing) sobre el array. Esta opción suele ser más eficiente, sobretodo si solo eliminamos del principio o del final del array:

    >>> import numpy as np

    #Eliminar el primer elemento
    >>> a = np.array([1, 2, 3, 4])
    >>> a = a[1:]
    >>> a
    array([2, 3, 4])


    # Eliminar el último elemento
    >>> a = np.array([1, 2, 3, 4])
    >>> a = a[:-1]
    >>> a
    array([1, 2, 3])


    # Eliminar el primero y el último:
    >>> a = np.array([1, 2, 3, 4])
    >>> a = a[1:-1]
    >>> a
    array([2, 3])

Si pretendías usar el elemento retornado por list.pop, en este caso debes primero obtener el elemento mediante indexado y luego aplicar la eliminación con alguno de los dos métodos.


También sería posible convertir el array en una lista o en una cola (si van a predominar las operaciones de agregado y eliminación en los extremos), teniendo en cuenta que puede haber implicaciones por el cambio de tipos y penalizaciones en la eficiencia al pasar a usar una lista o similar (además de no poder usar los métodos propios de NumPy con ella):

>>> import numpy as np

>>> a = np.array([1, 2, 3, 4])
>>> a = a.tolist() 
>>> a
[1, 2, 3, 4]

>>> a.pop()
>>> a
[1, 2, 3]

>>> del(a[0])
>>> a
>>> [2, 3]

Si no te interesa usar arrays de NumPy deberías simplemente hacer que tu función retorne una lista. Si I0s es simplemente el resultado de concatenar dos listas, como parces indicar en el código, basta con hacer justo eso:

>>> I0smallst = [1]
>>> I0bigst = [2,  5]
>>> I0s = I0smallst + I0bigst
>>> [1, 2, 5]
Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *