So fügen Sie einem NumPy-Array eine zusätzliche Spalte hinzu


292

Angenommen, ich habe ein NumPy-Array a:

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

Und ich möchte eine Spalte mit Nullen hinzufügen, um ein Array zu erhalten. b :

b = np.array([
    [1, 2, 3, 0],
    [2, 3, 4, 0]
    ])

Wie kann ich das in NumPy einfach machen?

Antworten:


181

Ich denke, eine einfachere Lösung und ein schnelleres Booten besteht darin, Folgendes zu tun:

import numpy as np
N = 10
a = np.random.rand(N,N)
b = np.zeros((N,N+1))
b[:,:-1] = a

Und Timings:

In [23]: N = 10

In [24]: a = np.random.rand(N,N)

In [25]: %timeit b = np.hstack((a,np.zeros((a.shape[0],1))))
10000 loops, best of 3: 19.6 us per loop

In [27]: %timeit b = np.zeros((a.shape[0],a.shape[1]+1)); b[:,:-1] = a
100000 loops, best of 3: 5.62 us per loop

16
Ich möchte (985,1) Form np araay an (985,2) np Array anhängen, um es (985,3) np Array zu machen, aber es funktioniert nicht. Ich erhalte die Fehlermeldung "Eingabearray konnte nicht von Form (985) in Form (985,1) gesendet werden". Was ist los mit meinem Code? Code: np.hstack (Daten, Daten1)
Ausreißer

5
@ Früher sollten Sie eine neue Frage stellen, anstatt eine in den Kommentaren dieser Frage zu stellen.
JoshAdel

4
@ JoshAdel: Ich habe Ihren Code auf ipython ausprobiert und glaube, es liegt ein Syntaxfehler vor. Vielleicht möchten Sie versuchen, a = np.random.rand((N,N))zua = np.random.rand(N,N)
hlin117

Ich denke, das ist ein Overkill für das, was OP verlangt hat. Die Antwort von Op ist passend!
lft93ryt

Dies ist nur ein Trick beim Anhängen, Einfügen oder Stapeln. und sollte nicht als Antwort akzeptiert werden. Ingenieure sollten in Betracht ziehen, die folgenden Antworten zu verwenden.
cinqS

325

np.r_[ ... ]und np.c_[ ... ] sind nützliche Alternativen zu vstackund hstackmit eckigen Klammern [] anstelle von round ().
Einige Beispiele:

: import numpy as np
: N = 3
: A = np.eye(N)

: np.c_[ A, np.ones(N) ]              # add a column
array([[ 1.,  0.,  0.,  1.],
       [ 0.,  1.,  0.,  1.],
       [ 0.,  0.,  1.,  1.]])

: np.c_[ np.ones(N), A, np.ones(N) ]  # or two
array([[ 1.,  1.,  0.,  0.,  1.],
       [ 1.,  0.,  1.,  0.,  1.],
       [ 1.,  0.,  0.,  1.,  1.]])

: np.r_[ A, [A[1]] ]              # add a row
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 0.,  1.,  0.]])
: # not np.r_[ A, A[1] ]

: np.r_[ A[0], 1, 2, 3, A[1] ]    # mix vecs and scalars
  array([ 1.,  0.,  0.,  1.,  2.,  3.,  0.,  1.,  0.])

: np.r_[ A[0], [1, 2, 3], A[1] ]  # lists
  array([ 1.,  0.,  0.,  1.,  2.,  3.,  0.,  1.,  0.])

: np.r_[ A[0], (1, 2, 3), A[1] ]  # tuples
  array([ 1.,  0.,  0.,  1.,  2.,  3.,  0.,  1.,  0.])

: np.r_[ A[0], 1:4, A[1] ]        # same, 1:4 == arange(1,4) == 1,2,3
  array([ 1.,  0.,  0.,  1.,  2.,  3.,  0.,  1.,  0.])

(Der Grund für eckige Klammern [] anstelle von round () ist, dass Python z. B. 1: 4 im Quadrat erweitert - die Wunder der Überladung.)


7
Ich habe nur nach Informationen darüber gesucht, und dies ist definitiv eine bessere Antwort als die akzeptierte, da es das Hinzufügen einer zusätzlichen Spalte am Anfang und am Ende abdeckt, nicht nur am Ende, wie die anderen Antworten
Ay0

2
@ Ay0 Genau, ich suchte nach einer Möglichkeit, meinem künstlichen neuronalen Netzwerk auf allen Ebenen gleichzeitig eine Bias-Einheit hinzuzufügen, und dies ist die perfekte Antwort.
gaborous

Und was ist, wenn Sie n Spalten gleichzeitig hinzufügen möchten ?
Riley

1
@ Riley, kannst du bitte ein Beispiel geben? Python 3 hat "iterierbares Entpacken", z np.c_[ * iterable ]. siehe Ausdruckslisten .
Denis

@denis, genau das habe ich gesucht!
Riley

148

Verwendung numpy.append:

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

>>> z = np.zeros((2,1), dtype=int64)
>>> z
array([[0],
       [0]])

>>> np.append(a, z, axis=1)
array([[1, 2, 3, 0],
       [2, 3, 4, 0]])

3
Dies ist hilfreich, wenn Sie kompliziertere Spalten einfügen.
Thomas Ahle

6
Dies ist einfacher als die Antwort von @JoshAdel, aber bei großen Datenmengen ist es langsamer. Ich würde zwischen den beiden wählen, abhängig von der Wichtigkeit der Lesbarkeit.
dvj

3
appendeigentlich nur anruftconcatenate
rll

53

Eine Möglichkeit, hstack zu verwenden , ist:

b = np.hstack((a, np.zeros((a.shape[0], 1), dtype=a.dtype)))

2
Ich denke, das ist die eleganteste Lösung.
Silvado

2
+1 - so würde ich es machen - du hast mich geschlagen, es als Antwort zu posten :).
Blair

3
Entfernen Sie den dtypeParameter, er wird nicht benötigt und ist sogar nicht erlaubt. Während Ihre Lösung elegant genug ist, achten Sie darauf, sie nicht zu verwenden, wenn Sie häufig an ein Array "anhängen" müssen. Wenn Sie nicht das gesamte Array auf einmal erstellen und später füllen können, erstellen Sie eine Liste der Arrays und hstackalles auf einmal.
Eumiro

1
@eumiro Ich bin nicht sicher, wie ich es geschafft habe, den dtype am falschen Ort zu bekommen, aber die np.zeros benötigt einen dtype, um zu verhindern, dass alles schwebt (während a int ist)
Peter Smit

42

Ich finde folgendes am elegantesten:

b = np.insert(a, 3, values=0, axis=1) # Insert values before column 3

Ein Vorteil von insertist, dass Sie damit auch Spalten (oder Zeilen) an anderen Stellen innerhalb des Arrays einfügen können. Anstatt einen einzelnen Wert einzufügen, können Sie auch ganz einfach einen ganzen Vektor einfügen, zum Beispiel die letzte Spalte duplizieren:

b = np.insert(a, insert_index, values=a[:,2], axis=1)

Was dazu führt:

array([[1, 2, 3, 3],
       [2, 3, 4, 4]])

Das Timing insertkönnte langsamer sein als die Lösung von JoshAdel:

In [1]: N = 10

In [2]: a = np.random.rand(N,N)

In [3]: %timeit b = np.hstack((a, np.zeros((a.shape[0], 1))))
100000 loops, best of 3: 7.5 µs per loop

In [4]: %timeit b = np.zeros((a.shape[0], a.shape[1]+1)); b[:,:-1] = a
100000 loops, best of 3: 2.17 µs per loop

In [5]: %timeit b = np.insert(a, 3, values=0, axis=1)
100000 loops, best of 3: 10.2 µs per loop

1
Das ist ziemlich ordentlich. Schade, dass ich insert(a, -1, ...)die Spalte nicht anhängen kann. Ich schätze, ich werde es stattdessen einfach voranstellen.
Thomas Ahle

2
@ThomasAhle Sie können eine Zeile oder Spalte anhängen, indem Sie die Größe in dieser Achse mit ermitteln a.shape[axis]. I. e. Zum Anhängen einer Zeile tun Sie dies np.insert(a, a.shape[0], 999, axis=0)und für eine Spalte tun Sie dies np.insert(a, a.shape[1], 999, axis=1).
Blubberdiblub

35

Ich war auch an dieser Frage interessiert und verglich die Geschwindigkeit von

numpy.c_[a, a]
numpy.stack([a, a]).T
numpy.vstack([a, a]).T
numpy.ascontiguousarray(numpy.stack([a, a]).T)               
numpy.ascontiguousarray(numpy.vstack([a, a]).T)
numpy.column_stack([a, a])
numpy.concatenate([a[:,None], a[:,None]], axis=1)
numpy.concatenate([a[None], a[None]], axis=0).T

die alle für jeden Eingabevektor dasselbe tun a. Zeitpunkte für das Wachstum a:

Geben Sie hier die Bildbeschreibung ein

Beachten Sie, dass alle nicht zusammenhängenden Varianten (insbesondere stack/ vstack) möglicherweise schneller sind als alle zusammenhängenden Varianten. column_stack(wegen seiner Klarheit und Geschwindigkeit) scheint eine gute Option zu sein, wenn Sie Kontiguität benötigen.


Code zur Reproduktion der Handlung:

import numpy
import perfplot

perfplot.save(
    "out.png",
    setup=lambda n: numpy.random.rand(n),
    kernels=[
        lambda a: numpy.c_[a, a],
        lambda a: numpy.ascontiguousarray(numpy.stack([a, a]).T),
        lambda a: numpy.ascontiguousarray(numpy.vstack([a, a]).T),
        lambda a: numpy.column_stack([a, a]),
        lambda a: numpy.concatenate([a[:, None], a[:, None]], axis=1),
        lambda a: numpy.ascontiguousarray(
            numpy.concatenate([a[None], a[None]], axis=0).T
        ),
        lambda a: numpy.stack([a, a]).T,
        lambda a: numpy.vstack([a, a]).T,
        lambda a: numpy.concatenate([a[None], a[None]], axis=0).T,
    ],
    labels=[
        "c_",
        "ascont(stack)",
        "ascont(vstack)",
        "column_stack",
        "concat",
        "ascont(concat)",
        "stack (non-cont)",
        "vstack (non-cont)",
        "concat (non-cont)",
    ],
    n_range=[2 ** k for k in range(20)],
    xlabel="len(a)",
    logx=True,
    logy=True,
)

1
Schöne Grafik! Ich dachte , du gerne wissen würde, dass unter der Haube stack, hstack, vstack, column_stack, dstacksind alle Funktionen Helfer oben auf gebaut np.concatenate. Beim Durchlaufen der Definition des Stapels stellte ich fest, dass der np.stack([a,a])Aufruf erfolgt np.concatenate([a[None], a[None]], axis=0). Es könnte schön sein, np.concatenate([a[None], a[None]], axis=0).Tdas Perfplot zu ergänzen , um zu zeigen, dass np.concatenatees immer mindestens so schnell sein kann, wie sein Helfer funktioniert.
Unutbu

@unutbu Hinzugefügt.
Nico Schlömer

Schöne Bibliothek, noch nie davon gehört! Interessant genug, dass ich genau die gleichen Plots habe, außer dass Stack und Concat die Plätze gewechselt haben (sowohl in Ascont- als auch in Non-Cont-Varianten). Außerdem wurden concat-column und column_stack ebenfalls ausgetauscht.
Antony Hatchkins

1
Wow, liebe diese Pläne!
Jhegedus

Es scheint, dass bei einer rekursiven Operation zum Anhängen einer Spalte an ein Array, z. B. b = [b, a], einige Befehle nicht funktionieren (ein Fehler über ungleiche Dimensionen wird ausgelöst). Die einzigen zwei, die mit Arrays ungleicher Größe zu arbeiten scheinen (dh wenn eines eine Matrix und eines ein 1d-Vektor ist), sind c_undcolumn_stack
Confounded

29

Meiner Ansicht nach:

np.column_stack((a, zeros(shape(a)[0])))

ist eleganter.


12

np.concatenate funktioniert auch

>>> a = np.array([[1,2,3],[2,3,4]])
>>> a
array([[1, 2, 3],
       [2, 3, 4]])
>>> z = np.zeros((2,1))
>>> z
array([[ 0.],
       [ 0.]])
>>> np.concatenate((a, z), axis=1)
array([[ 1.,  2.,  3.,  0.],
       [ 2.,  3.,  4.,  0.]])

np.concatenatescheint dreimal schneller zu sein als np.hstackbei 2x1-, 2x2- und 2x3-Matrizen. np.concatenatewar in meinen Experimenten auch etwas schneller als das manuelle Kopieren der Matrizen in eine leere Matrix. Das stimmt mit der Antwort von Nico Schlömer überein.
Lenar Hoyt

11

Angenommen, es Mist ein (100,3) ndarray und yein (100,) ndarray appendkann wie folgt verwendet werden:

M=numpy.append(M,y[:,None],1)

Der Trick ist zu verwenden

y[:, None]

Dies wird yin ein (100, 1) 2D-Array konvertiert .

M.shape

jetzt gibt

(100, 4)

Du bist ein Held, weißt du das?! Genau das ziehe ich mir seit 1 Stunde die Haare! Ty!
John Doe

8

Ich mag JoshAdels Antwort wegen des Fokus auf Leistung. Eine geringfügige Leistungsverbesserung besteht darin, den Aufwand für die Initialisierung mit Nullen zu vermeiden, nur um überschrieben zu werden. Dies hat einen messbaren Unterschied, wenn N groß ist, leer anstelle von Nullen verwendet wird und die Spalte mit Nullen als separater Schritt geschrieben wird:

In [1]: import numpy as np

In [2]: N = 10000

In [3]: a = np.ones((N,N))

In [4]: %timeit b = np.zeros((a.shape[0],a.shape[1]+1)); b[:,:-1] = a
1 loops, best of 3: 492 ms per loop

In [5]: %timeit b = np.empty((a.shape[0],a.shape[1]+1)); b[:,:-1] = a; b[:,-1] = np.zeros((a.shape[0],))
1 loops, best of 3: 407 ms per loop

Sie können Broadcasting verwenden, um die letzte Spalte mit Nullen (oder einem anderen Wert) zu füllen, die möglicherweise besser lesbar sind : b[:,-1] = 0. Bei sehr großen Arrays wird der Leistungsunterschied np.insert()vernachlässigbar, was np.insert()aufgrund seiner Prägnanz wünschenswerter sein könnte.
Blubberdiblub

7

np.insert dient auch dem Zweck.

matA = np.array([[1,2,3], 
                 [2,3,4]])
idx = 3
new_col = np.array([0, 0])
np.insert(matA, idx, new_col, axis=1)

array([[1, 2, 3, 0],
       [2, 3, 4, 0]])

Hier werden Werte new_colvor einem bestimmten Index hier idxentlang einer Achse eingefügt. Mit anderen Worten, die neu eingefügten Werte belegen die idxSpalte und verschieben das, was ursprünglich dort und danach war, idxrückwärts.


1
Beachten Sie, dass dies insertnicht vorhanden ist, wie unter dem Namen der Funktion angenommen werden könnte (siehe in der Antwort verknüpfte Dokumente).
Jneuendorf

5

Fügen Sie einem numpy-Array eine zusätzliche Spalte hinzu:

Numpys np.appendMethode verwendet drei Parameter, die ersten beiden sind 2D-Numpy-Arrays und der dritte ist ein Achsenparameter, der angibt, entlang welcher Achse angehängt werden soll:

import numpy as np  
x = np.array([[1,2,3], [4,5,6]]) 
print("Original x:") 
print(x) 

y = np.array([[1], [1]]) 
print("Original y:") 
print(y) 

print("x appended to y on axis of 1:") 
print(np.append(x, y, axis=1)) 

Drucke:

Original x:
[[1 2 3]
 [4 5 6]]
Original y:
[[1]
 [1]]
x appended to y on axis of 1:
[[1 2 3 1]
 [4 5 6 1]]

Beachten Sie, dass Sie hier y an x ​​anhängen, anstatt x an y anzuhängen. Deshalb befindet sich der Spaltenvektor von y im Ergebnis rechts von den Spalten von x.
Brian Popeck

4

Ein bisschen zu spät zur Party, aber noch hat niemand diese Antwort gepostet. Der Vollständigkeit halber: Sie können dies mit Listenverständnis auf einem einfachen Python-Array tun:

source = a.tolist()
result = [row + [0] for row in source]
b = np.array(result)

4

Für mich sieht der nächste Weg ziemlich intuitiv und einfach aus.

zeros = np.zeros((2,1)) #2 is a number of rows in your array.   
b = np.hstack((a, zeros))

3

In meinem Fall musste ich einem NumPy-Array eine Spalte mit Einsen hinzufügen

X = array([ 6.1101, 5.5277, ... ])
X.shape => (97,)
X = np.concatenate((np.ones((m,1), dtype=np.int), X.reshape(m,1)), axis=1)

Nach X.shape => (97, 2)

array([[ 1. , 6.1101],
       [ 1. , 5.5277],
...

1

Hierfür gibt es eine spezielle Funktion. Es heißt numpy.pad

a = np.array([[1,2,3], [2,3,4]])
b = np.pad(a, ((0, 0), (0, 1)), mode='constant', constant_values=0)
print b
>>> array([[1, 2, 3, 0],
           [2, 3, 4, 0]])

Folgendes steht in der Dokumentationszeichenfolge:

Pads an array.

Parameters
----------
array : array_like of rank N
    Input array
pad_width : {sequence, array_like, int}
    Number of values padded to the edges of each axis.
    ((before_1, after_1), ... (before_N, after_N)) unique pad widths
    for each axis.
    ((before, after),) yields same before and after pad for each axis.
    (pad,) or int is a shortcut for before = after = pad width for all
    axes.
mode : str or function
    One of the following string values or a user supplied function.

    'constant'
        Pads with a constant value.
    'edge'
        Pads with the edge values of array.
    'linear_ramp'
        Pads with the linear ramp between end_value and the
        array edge value.
    'maximum'
        Pads with the maximum value of all or part of the
        vector along each axis.
    'mean'
        Pads with the mean value of all or part of the
        vector along each axis.
    'median'
        Pads with the median value of all or part of the
        vector along each axis.
    'minimum'
        Pads with the minimum value of all or part of the
        vector along each axis.
    'reflect'
        Pads with the reflection of the vector mirrored on
        the first and last values of the vector along each
        axis.
    'symmetric'
        Pads with the reflection of the vector mirrored
        along the edge of the array.
    'wrap'
        Pads with the wrap of the vector along the axis.
        The first values are used to pad the end and the
        end values are used to pad the beginning.
    <function>
        Padding function, see Notes.
stat_length : sequence or int, optional
    Used in 'maximum', 'mean', 'median', and 'minimum'.  Number of
    values at edge of each axis used to calculate the statistic value.

    ((before_1, after_1), ... (before_N, after_N)) unique statistic
    lengths for each axis.

    ((before, after),) yields same before and after statistic lengths
    for each axis.

    (stat_length,) or int is a shortcut for before = after = statistic
    length for all axes.

    Default is ``None``, to use the entire axis.
constant_values : sequence or int, optional
    Used in 'constant'.  The values to set the padded values for each
    axis.

    ((before_1, after_1), ... (before_N, after_N)) unique pad constants
    for each axis.

    ((before, after),) yields same before and after constants for each
    axis.

    (constant,) or int is a shortcut for before = after = constant for
    all axes.

    Default is 0.
end_values : sequence or int, optional
    Used in 'linear_ramp'.  The values used for the ending value of the
    linear_ramp and that will form the edge of the padded array.

    ((before_1, after_1), ... (before_N, after_N)) unique end values
    for each axis.

    ((before, after),) yields same before and after end values for each
    axis.

    (constant,) or int is a shortcut for before = after = end value for
    all axes.

    Default is 0.
reflect_type : {'even', 'odd'}, optional
    Used in 'reflect', and 'symmetric'.  The 'even' style is the
    default with an unaltered reflection around the edge value.  For
    the 'odd' style, the extented part of the array is created by
    subtracting the reflected values from two times the edge value.

Returns
-------
pad : ndarray
    Padded array of rank equal to `array` with shape increased
    according to `pad_width`.

Notes
-----
.. versionadded:: 1.7.0

For an array with rank greater than 1, some of the padding of later
axes is calculated from padding of previous axes.  This is easiest to
think about with a rank 2 array where the corners of the padded array
are calculated by using padded values from the first axis.

The padding function, if used, should return a rank 1 array equal in
length to the vector argument with padded values replaced. It has the
following signature::

    padding_func(vector, iaxis_pad_width, iaxis, kwargs)

where

    vector : ndarray
        A rank 1 array already padded with zeros.  Padded values are
        vector[:pad_tuple[0]] and vector[-pad_tuple[1]:].
    iaxis_pad_width : tuple
        A 2-tuple of ints, iaxis_pad_width[0] represents the number of
        values padded at the beginning of vector where
        iaxis_pad_width[1] represents the number of values padded at
        the end of vector.
    iaxis : int
        The axis currently being calculated.
    kwargs : dict
        Any keyword arguments the function requires.

Examples
--------
>>> a = [1, 2, 3, 4, 5]
>>> np.pad(a, (2,3), 'constant', constant_values=(4, 6))
array([4, 4, 1, 2, 3, 4, 5, 6, 6, 6])

>>> np.pad(a, (2, 3), 'edge')
array([1, 1, 1, 2, 3, 4, 5, 5, 5, 5])

>>> np.pad(a, (2, 3), 'linear_ramp', end_values=(5, -4))
array([ 5,  3,  1,  2,  3,  4,  5,  2, -1, -4])

>>> np.pad(a, (2,), 'maximum')
array([5, 5, 1, 2, 3, 4, 5, 5, 5])

>>> np.pad(a, (2,), 'mean')
array([3, 3, 1, 2, 3, 4, 5, 3, 3])

>>> np.pad(a, (2,), 'median')
array([3, 3, 1, 2, 3, 4, 5, 3, 3])

>>> a = [[1, 2], [3, 4]]
>>> np.pad(a, ((3, 2), (2, 3)), 'minimum')
array([[1, 1, 1, 2, 1, 1, 1],
       [1, 1, 1, 2, 1, 1, 1],
       [1, 1, 1, 2, 1, 1, 1],
       [1, 1, 1, 2, 1, 1, 1],
       [3, 3, 3, 4, 3, 3, 3],
       [1, 1, 1, 2, 1, 1, 1],
       [1, 1, 1, 2, 1, 1, 1]])

>>> a = [1, 2, 3, 4, 5]
>>> np.pad(a, (2, 3), 'reflect')
array([3, 2, 1, 2, 3, 4, 5, 4, 3, 2])

>>> np.pad(a, (2, 3), 'reflect', reflect_type='odd')
array([-1,  0,  1,  2,  3,  4,  5,  6,  7,  8])

>>> np.pad(a, (2, 3), 'symmetric')
array([2, 1, 1, 2, 3, 4, 5, 5, 4, 3])

>>> np.pad(a, (2, 3), 'symmetric', reflect_type='odd')
array([0, 1, 1, 2, 3, 4, 5, 5, 6, 7])

>>> np.pad(a, (2, 3), 'wrap')
array([4, 5, 1, 2, 3, 4, 5, 1, 2, 3])

>>> def pad_with(vector, pad_width, iaxis, kwargs):
...     pad_value = kwargs.get('padder', 10)
...     vector[:pad_width[0]] = pad_value
...     vector[-pad_width[1]:] = pad_value
...     return vector
>>> a = np.arange(6)
>>> a = a.reshape((2, 3))
>>> np.pad(a, 2, pad_with)
array([[10, 10, 10, 10, 10, 10, 10],
       [10, 10, 10, 10, 10, 10, 10],
       [10, 10,  0,  1,  2, 10, 10],
       [10, 10,  3,  4,  5, 10, 10],
       [10, 10, 10, 10, 10, 10, 10],
       [10, 10, 10, 10, 10, 10, 10]])
>>> np.pad(a, 2, pad_with, padder=100)
array([[100, 100, 100, 100, 100, 100, 100],
       [100, 100, 100, 100, 100, 100, 100],
       [100, 100,   0,   1,   2, 100, 100],
       [100, 100,   3,   4,   5, 100, 100],
       [100, 100, 100, 100, 100, 100, 100],
       [100, 100, 100, 100, 100, 100, 100]])
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.