15 Stimmen

Wie kann man ein Numpy-Array aus einer Liste von Numpy-Arrays entfernen?

Wenn ich eine Liste von Numpy-Arrays haben, dann mit remove-Methode gibt einen Wert Fehler.

Zum Beispiel:

import numpy as np

l = [np.array([1,1,1]),np.array([2,2,2]),np.array([3,3,3])]

l.remove(np.array([2,2,2]))

Würde mir

WertFehler: Der Wahrheitswert eines Arrays mit mehr als einem Element ist mehrdeutig. Verwenden Sie a.any() oder a.all()

Ich kann nicht scheinen, um die all() zu arbeiten, ist es einfach nicht möglich?

0 Stimmen

Nur damit Sie es wissen, es ist keine gute Idee, die list als Variable, da es in Python ein Schlüsselwort ist. Das kann Ihnen später zum Verhängnis werden.

0 Stimmen

Ja, danke, ich wurde gebissen, während ich herumspielte und versuchte, dieses Problem zu lösen, indem ich die Arrays mit list() in Listen umwandelte und dann remove und so weiter verwendete.

15voto

Justin Peel Punkte 46114

Das Problem dabei ist, dass beim Vergleich zweier Numpy-Arrays mit ==, wie in den Methoden remove() und index(), ein Numpy-Array mit booleschen Werten (die elementweisen Vergleiche) zurückgegeben wird, das als mehrdeutig interpretiert wird. Eine gute Möglichkeit, zwei Numpy-Arrays auf Gleichheit zu vergleichen, ist die Verwendung der Numpy-Funktion array_equal().

Da die remove()-Methode von lists kein Schlüsselargument hat (wie sort()), denke ich, dass Sie dafür eine eigene Funktion erstellen müssen. Hier ist eine, die ich gemacht habe:

def removearray(L,arr):
    ind = 0
    size = len(L)
    while ind != size and not np.array_equal(L[ind],arr):
        ind += 1
    if ind != size:
        L.pop(ind)
    else:
        raise ValueError('array not found in list.')

Wenn Sie es schneller brauchen, können Sie es in Cython umwandeln.

3voto

lprsd Punkte 80189

Hier ist es:

list.pop(1)

Aktualisierung:

list.pop(list.index(element))

Ich glaube nicht, dass Sie um das Durchlaufen der Liste herumkommen, um die Position des Elements zu finden. Machen Sie sich keine Gedanken darüber. Python wird standardmäßig einen guten Suchalgorithmus verwenden, um es mit dem geringsten Aufwand für Sie zu finden.

2voto

thomas Punkte 259

Python Grundfunktionalitäten verwenden

Die folgende Lösung verwendet die list.index(element) Methode aus dem Liste der Arrays.

Auf der Suche nach einem numpy.ndarray muss in der Lage sein, numpy.ndarray-Instanzen zu hashen. Daher müssen wir einen einen Hashing-Algorithmus implementieren. Dies ist recht einfach, auch wenn der vorgestellte Code etwas lang aussieht. Die meisten Zeilen werden für die Überprüfung von Randfällen oder das Hinzufügen von Kommentaren verwendet.

Sie können den Code in eine Datei kopieren und über die Befehlszeile ausführen oder einem SDK wie PyCharm ausführen.

Das müssen Sie wissen

  • [].index(element)
  • Hash (Hashing und Hash-Kollisionen)
  • wie man ein Numpy-Array hasht

Anmerkung:

  • Hash-Kollisionen können zu falschen Entscheidungen führen, die Sie selbst treffen müssen über die Wahrscheinlichkeit und die Auswirkungen
  • wird nur das erste Vorkommen des Arrays entfernt, falls es mehrere mit denselben Daten gibt.

import numpy as np

def remove(array, arrays):
    """
    Remove the `array` from the `list` of `arrays`
    Operates inplace on the `list` of `arrays` given

    :param array: `np.ndarray`
    :param arrays: `list:np.ndarray`
    :return: None
    """

    assert isinstance(arrays, list), f'Expected a list, got {type(arrays)} instead'
    assert isinstance(array, np.ndarray), f'Expected a numpy.ndarray, got {type(array)} instead'
    for a in arrays:
        assert isinstance(a, np.ndarray), f'Expected a numpy.ndarray instances in arrays, found {type(a)} instead'

    # Numpy ndarrays are not hashable by default, so we create
    # our own hashing algorithm. The following will do the job ...
    def _hash(a):
        return hash(a.tobytes())

    try:
        # We create a list of hashes and search for the index
        # of the hash of the array we want to remove.
        index = [_hash(a) for a in arrays].index(_hash(array))
    except ValueError as e:
        # It might be, that the array is not in the list at all.
        print(f'Array not in list. Leaving input unchanged.')
    else:
        # Only in the case of no exception we pop the array
        # with the same index/position from the original
        # arrays list
        arrays.pop(index)

if __name__ == '__main__':

    # Let's start with the following arrays as given in the question
    arrays = [np.array([1, 1, 1]), np.array([2, 2, 2]), np.array([3, 3, 3])]
    print(arrays)

    # And remove this array instance from it.
    # Note, this is a new instance, so the object id is
    # different. Structure and values coincide.
    remove(np.array([2, 2, 2]), arrays)

    # Let's check the result
    print(arrays)

    # Let's check, whether our edge case handling works.
    remove(np.array([1, 2, 3]), arrays)

1voto

thomas Punkte 259

Verwendung von Basisfunktionalitäten aus Python und Numpy

Sie können den folgenden Einzeiler ausführen, um das Ergebnis zu erhalten ...

import numpy as np

# Your inputs ...
l = [np.array([1, 1, 1]), np.array([2, 2, 2]), np.array([3, 3, 3])]
array_to_remove = np.array([2, 2, 2])

# My result ...
result = [a for a, skip in zip(l, [np.allclose(a, array_to_remove) for a in l]) if not skip]

print(result)

... oder fügen Sie das Folgende in ein Skript ein und experimentieren Sie ein wenig.

Sie benötigen

  • numpy.allclose zum Vergleich von Numpy-Arrays bis hin zu Fließkomma-Darstellungsfehlern
  • zip
  • Listenverstehen
  • das Konzept der Maske

Achtung, ...

  • diese Lösung liefert eine Liste ohne alle Vorkommen des gesuchten Arrays
  • die zurückgegebene Liste enthält Verweise auf die np.ndarray-Instanzen, auf die auch in der ursprünglichen Liste verwiesen wird. Es gibt keine Kopien!

import numpy as np

def remove(array, arrays):
    """
    Remove the `array` from the `list` of `arrays`
    Returns list with remaining arrays by keeping the order.

    :param array: `np.ndarray`
    :param arrays: `list:np.ndarray`
    :return: `list:np.ndarray`
    """

    assert isinstance(arrays, list), f'Expected a list, got {type(arrays)} instead'
    assert isinstance(array, np.ndarray), f'Expected a numpy.ndarray, got {type(array)} instead'
    for a in arrays:
        assert isinstance(a, np.ndarray), f'Expected a numpy.ndarray instances in arrays, found {type(a)} instead'

    # We use np.allclose for comparing arrays, this will work even if there are
    # floating point representation differences.
    # The idea is to create a boolean mask of the same lenght as the input arrays.
    # Then we loop over the arrays-elements and the mask-elements and skip the
    # flagged elements
    mask = [np.allclose(a, array) for a in arrays]
    return [a for a, skip in zip(arrays, mask) if not skip]

if __name__ == '__main__':

    # Let's start with the following arrays as given in the question
    arrays = [np.array([1, 1, 1]), np.array([2, 2, 2]), np.array([3, 3, 3])]
    print(arrays)

    # And remove this array instance from it.
    # Note, this is a new instance, so the object id is
    # different. Structure and values coincide.
    _arrays = remove(np.array([2, 2, 2]), arrays)

    # Let's check the result
    print(_arrays)

    # Let's check, whether our edge case handling works.
    print(arrays)
    _arrays = remove(np.array([1, 2, 3]), arrays)
    print(_arrays)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X