WebHU - Programozási kérdések és válaszok

Miért ad vissza a numpy ndarray beszúrása és hozzáfűzése új tömböt az eredeti tömb módosítása helyett?

A numpy ndarray esetében nincs hozzáfűzés és beszúrás, mint a natív python listáknál.

a = np.array([1, 2, 3])
a.append(5)  # this does not work
a = np.append(a, 5)  # this is the only way

mivel a natív python listák esetében

a = [1, 2, 3]
a.append(4)  # this modifies a
a  # [1, 2, 3, 4]

Miért tervezték a numpy ndarray-t ilyenre? Az ndarray egy alosztályát írom, van valami módja az "hozzáfűzés" megvalósítására, mint a natív python tömbök?

15.12.2018

Válaszok:


1

A NumPy erősen kihasználja a nézeteket, egy olyan funkciót, amelyet a Python listák nem támogatnak. A nézet olyan tömb, amely egy másik objektum memóriáját használja ahelyett, hogy saját memóriája lenne; például a következő részletben

a = numpy.arange(5)
b = a[1:3]

A b a a nézete.

A nézetek nagyon gyengén működnének együtt egy helyben append vagy más helyben végrehajtott méretmódosító művelettel. A tömbök hirtelen nem a tömbök nézetei lennének, amelyeknek nézniük kellene, vagy a felszabadított memória nézetei lennének, vagy megjósolhatatlan lenne, hogy az egyik tömbön lévő append hatással lesz-e arra a tömbre, amelynek nézete volt, vagy mindenféle más probléma. . Például hogyan nézne ki a a a b.append(6) után? Vagy hogyan nézne ki b a.clear() után? És milyen teljesítménygaranciákat tudna vállalni? Valószínűleg nem a list.append amortizált állandó időgarancia.

Ha append akarja, valószínűleg nem kellene NumPy tömböket használnia; használjon listát, és készítsen a listából egy tömböt, ha végzett a hozzáfűzéssel.

15.12.2018

2

A ndarray rögzített méretű adatpufferrel jön létre – éppen akkora, hogy az elemeket reprezentáló bájtokat tárolja.

arr.nbytes == arr.itemsize * arr.size

A arr.resize helyben módosíthatja a tömböt. De olvassa el a dokumentumait, hogy megtudja a korlátokat, különösen a saját adatok birtoklásával kapcsolatban. Ez egyike azon kevés helyi műveleteknek, és nem használják olyan gyakran.

Ezzel szemben a Python-lista az objektummutatókat egy pufferben tárolja. A pufferben van némi növekedési lehetőség, amely lehetővé teszi a hatékony append. Csak egy új mutatót kell hozzáadnia a pufferhez. Amikor a puffer megtelik, új nagyobb puffert foglal le, és lemásolja a mutatókat.

Egy 1d tömb esetén a ndarray és list pufferei hasonlóak lesznek, legalább 4 vagy 8 bájtos numerikus dtype esetén. A többdimenziós tömbök esetében azonban az adatpuffer nagyon nagy lehet (az összes dimenzió szorzata), míg egy egyenértékű beágyazott tömb felső puffere csak a listák külső rétegére (a „sorokra”) mutató mutatókat tartalmaz.

Az objektum dtype tömbök listaként tárolják a mutatókat, de az adatpuffer továbbra is rögzített méretű (nincs növekedési terület). A teljesítmény a numerikus tömbök és listák között rejlik.

El tudom képzelni, hogy írok egy inplace hozzáfűzést, amely a resize metódust használja, majd az új érték(ek) másolása a 0 kitöltésekre.

In [96]: arr = np.array([[1,3],[2,7]])
In [97]: arr.resize(3,2)
In [98]: arr
Out[98]: 
array([[1, 3],
       [2, 7],
       [0, 0]])
In [99]: arr[-1,:] = 10,11
In [100]: arr
Out[100]: 
array([[ 1,  3],
       [ 2,  7],
       [10, 11]])

De figyeljük meg, mi történik az értékekkel, ha átméretezünk egy belső tengelyt:

In [101]: arr = np.array([[1,3],[2,7]])
In [102]: arr.resize(2,3)
In [103]: arr
Out[103]: 
array([[1, 3, 2],
       [7, 0, 0]])

Tehát ez a fajta hozzáfűzés meglehetősen korlátozott a concatenate-hez (és annak összes 'verem' származékához) képest.


Megnézted a np.append kódját? Miután megbizonyosodott arról, hogy az argumentumok tömbök, és módosítja az alakjukat, a következőket teszi:

concatenate((arr, values), axis=axis)

Más szóval, ez csak egy alternatív módja a concatenate hívásának. Valószínűleg ez a legjobb egyetlen érték hozzáadásához egy 1d tömbhöz. Nem szabad ismételten használni egy ciklusban, pontosan azért, mert új tömböt ad vissza, és így viszonylag drága. Ellenkező esetben a használata sok felhasználót megzavar. Néhányan figyelmen kívül hagyják a tengely paramétert. Másoknak gondjuk van a megfelelő „üres” tömb létrehozásával. A Concatenate-nek is vannak ilyen problémái, de legalább a felhasználóknak tudatosan kell foglalkozniuk az alakzatok illesztésével.

A np.insert sokkal bonyolultabb. Különböző dolgokat hajt végre attól függően, hogy az indexek (obj) számok, szeletek vagy számok listája. Az egyik megközelítés a megfelelő méretű céltömb létrehozása, szeletek másolása az eredetiből, és az értékek beillesztése a megfelelő helyekre. Egy másik, hogy logikai maszkot használunk az értékek megfelelő helyekre másolásához. Mindkettőnek többdimenziósnak kell lennie – egy tengely mentén szúr be, de a többi mérethez a megfelelő slice(None)-t kell használnia. Ez sokkal bonyolultabb, mint a listabeszúrás, amely egy objektumot (mutatót) szúr be egy helyre az 1d-ben.

15.12.2018
  • Nem akartam megemlíteni a ndarray.resize-et – ez a segfault/tetszőleges kódvégrehajtási sebezhetőségi szint veszélyes (különösen az alosztályozás által hozzáadott bonyodalmakkal, mint például a __array_wrap__ és más mechanizmusokkal, amelyek miatt a példányok gyakrabban jelennek meg, vagy az extra hivatkozások miatt egy alosztály append metódusának indirekt szintje), nem működik PyPy-n, a hatékonyság érdekében a realloc viselkedésére támaszkodik, stb. Létezik, de szinte biztosan nem járható út. 16.12.2018
  • Új anyagok

    A rádiógomb ellenőrzött eseményének használata a jQueryben
    Ebben a cikkben látni fogjuk, hogyan kell dolgozni a jquery választógombbal ellenőrzött eseményeivel. A választógombok HTML gombok, amelyek segítenek kiválasztani egyetlen értéket egy csoportból...

    Körkörös függőségek megoldása terraformban adatforrásokkal – lépésről lépésre
    Mi az a körkörös függőségek Dolgozzunk egy egyszerű eseten, amikor az SQS-sor és az S3-vödör közötti körkörös függőség problémája van egy egymástól függő címkeérték miatt. provider..

    Miért érdemes elkezdeni a kódolást 2023-ban?
    01100011 01101111 01100100 01100101 — beep boop beep boop Világunk folyamatosan fejlődik a technológia körül, és naponta fejlesztenek új technológiákat a valós problémák megoldására. Amint..

    🎙 Random Noise #2  – Örökbefogadás és hit
    az analitika íratlan világának gondozása Szeretné, hogy ezek a frissítések a postaládájába kerüljenek? Iratkozzon fel itt . "Ha önvezető autókat gyártanak, akkor mi miért ne..

    A legrosszabb politika és prediktív modellek májátültetésre jelöltek számára az Egyesült Államokban
    A máj (vagy óangolul lifer) az emberi test legnehezebb belső szervére utal, amely csendesen működik a nap 24 órájában. Mit csinál a máj? 500 feladatot hajt végre a szervezet egészségének..

    5 webhely, amely 2022-ben fejleszti front-end fejlesztői készségeit
    Frontendmentor.io A tényleges projektek létrehozásával a Frontendmentor.io segítséget nyújt a front-end kódolási képességeinek fejlesztésében. A kódolást azután kezdheti meg, hogy..

    Mikor kell használni a Type-t az interfészhez képest a TypeScriptben?
    A TypeScript a JavaScript gépelt szuperkészlete, amely statikus gépelést ad a nyelvhez. Ez megkönnyíti a robusztus és karbantartható kód írását azáltal, hogy a hibákat a fordítási időben..