Từ mảng ND đến mảng 1D


141

Nói rằng tôi có một mảng a:

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

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

Tôi muốn chuyển đổi nó thành một mảng 1D (tức là một vectơ cột):

b = np.reshape(a, (1,np.product(a.shape)))

nhưng điều này trở lại

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

không giống như:

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

Tôi có thể lấy phần tử đầu tiên của mảng này để tự chuyển đổi nó thành mảng 1D:

b = np.reshape(a, (1,np.product(a.shape)))[0]

nhưng điều này đòi hỏi tôi phải biết mảng ban đầu có bao nhiêu kích thước (và nối [0] khi làm việc với các kích thước cao hơn)

Có một cách độc lập kích thước để có được một vectơ cột / hàng từ một ndarray tùy ý không?

Câu trả lời:


277

Sử dụng np.ravel (cho chế độ xem 1D) hoặc np.ndarray.flatten (đối với bản sao 1D) hoặc np.ndarray.flat (đối với trình lặp 1D):

In [12]: a = np.array([[1,2,3], [4,5,6]])

In [13]: b = a.ravel()

In [14]: b
Out[14]: array([1, 2, 3, 4, 5, 6])

Lưu ý rằng ravel()trả về một viewtrong akhi có thể. Vì vậy, sửa đổi bcũng sửa đổi a. ravel()trả về a viewkhi các phần tử 1D liền kề trong bộ nhớ, nhưng sẽ trả về copynếu, ví dụ, ađược tạo từ việc cắt một mảng khác bằng cách sử dụng kích thước bước không đơn vị (ví dụ a = x[::2]).

Nếu bạn muốn có một bản sao chứ không phải là một khung nhìn, hãy sử dụng

In [15]: c = a.flatten()

Nếu bạn chỉ muốn một trình vòng lặp, hãy sử dụng np.ndarray.flat:

In [20]: d = a.flat

In [21]: d
Out[21]: <numpy.flatiter object at 0x8ec2068>

In [22]: list(d)
Out[22]: [1, 2, 3, 4, 5, 6]

4
<pedantic> Trong ví dụ này, ravel()trả về một khung nhìn, nhưng điều đó không phải lúc nào cũng đúng. Có những trường hợp ravel()trả về một bản sao. </ Pedantic>
Warren Weckesser

3
a.ravel()có vẻ là nhanh gấp ba lần a.reshape(-1). a.flatten()là cách chậm hơn, vì nó cần phải tạo một bản sao.
BallpointBen

25
In [14]: b = np.reshape(a, (np.product(a.shape),))

In [15]: b
Out[15]: array([1, 2, 3, 4, 5, 6])

hoặc đơn giản:

In [16]: a.flatten()
Out[16]: array([1, 2, 3, 4, 5, 6])

11
Có thể sử dụng b = a.reshape(-1)cho ngắn trong ví dụ đầu tiên.
Syrtis Major

5

Một trong những cách đơn giản nhất là sử dụng flatten(), như ví dụ này:

 import numpy as np

 batch_y =train_output.iloc[sample, :]
 batch_y = np.array(batch_y).flatten()

Mảng của tôi là như thế này:

    0
0   6
1   6
2   5
3   4
4   3
.
.
.

Sau khi sử dụng flatten():

array([6, 6, 5, ..., 5, 3, 6])

Đây cũng là giải pháp cho các lỗi thuộc loại này:

Cannot feed value of shape (100, 1) for Tensor 'input/Y:0', which has shape '(?,)' 

4

Đối với danh sách các mảng với kích thước khác nhau, sử dụng như sau:

import numpy as np

# ND array list with different size
a = [[1],[2,3,4,5],[6,7,8]]

# stack them
b = np.hstack(a)

print(b)

Đầu ra:

[1 2 3 4 5 6 7 8]


Làm thế nào bạn sẽ có được hình dạng atrở lại từ b?
dvdblk

Nếu bạn muốn chia 1D thành khối. Xem stackoverflow.com/a/8495740/6117565
bikram

4

Tôi muốn xem kết quả điểm chuẩn của các chức năng được đề cập trong các câu trả lời bao gồm cả unutbu .

Cũng muốn chỉ ra rằng tài liệu numpy khuyên bạn nên sử dụng arr.reshape(-1)trong trường hợp xem là thích hợp hơn. (mặc dù ravelnhanh hơn trong kết quả sau)


TL; DR : np.ravellà hiệu suất cao nhất (với số lượng rất nhỏ).

Điểm chuẩn

Chức năng:

phiên bản gọn gàng: '1.18.0'

Thời gian thực hiện trên các ndarraykích cỡ khác nhau

+-------------+----------+-----------+-----------+-------------+
|  function   |   10x10  |  100x100  | 1000x1000 | 10000x10000 |
+-------------+----------+-----------+-----------+-------------+
| ravel       | 0.002073 |  0.002123 |  0.002153 |    0.002077 |
| reshape(-1) | 0.002612 |  0.002635 |  0.002674 |    0.002701 |
| flatten     | 0.000810 |  0.007467 |  0.587538 |  107.321913 |
| flat        | 0.000337 |  0.000255 |  0.000227 |    0.000216 |
+-------------+----------+-----------+-----------+-------------+

Phần kết luận

ravelreshape(-1)thời gian thực hiện là nhất quán và độc lập với kích thước ndarray. Tuy nhiên, ravelnhanh hơn một chút, nhưng reshapecung cấp sự linh hoạt trong việc định hình lại kích thước. (có thể đó là lý do tại sao tài liệu numpy khuyên bạn nên sử dụng nó thay thế. Hoặc có thể có một số trường hợp reshapetrả về lượt xem và ravelkhông).
Nếu bạn đang xử lý ndarray kích thước lớn, việc sử dụng flattencó thể gây ra vấn đề về hiệu suất. Đề nghị không sử dụng nó. Trừ khi bạn cần một bản sao của dữ liệu để làm việc khác.

Mã đã sử dụng

import timeit
setup = '''
import numpy as np
nd = np.random.randint(10, size=(10, 10))
'''

timeit.timeit('nd = np.reshape(nd, -1)', setup=setup, number=1000)
timeit.timeit('nd = np.ravel(nd)', setup=setup, number=1000)
timeit.timeit('nd = nd.flatten()', setup=setup, number=1000)
timeit.timeit('nd.flat', setup=setup, number=1000)

0

Mặc dù điều này không sử dụng định dạng mảng np, (để lười sửa đổi mã của tôi), điều này sẽ làm những gì bạn muốn ... Nếu, bạn thực sự muốn một vectơ cột bạn sẽ muốn hoán chuyển kết quả vectơ. Tất cả phụ thuộc vào cách bạn dự định sử dụng cái này.

def getVector(data_array,col):
    vector = []
    imax = len(data_array)
    for i in range(imax):
        vector.append(data_array[i][col])
    return ( vector )
a = ([1,2,3], [4,5,6])
b = getVector(a,1)
print(b)

Out>[2,5]

Vì vậy, nếu bạn cần hoán vị, bạn có thể làm một cái gì đó như thế này:

def transposeArray(data_array):
    # need to test if this is a 1D array 
    # can't do a len(data_array[0]) if it's 1D
    two_d = True
    if isinstance(data_array[0], list):
        dimx = len(data_array[0])
    else:
        dimx = 1
        two_d = False
    dimy = len(data_array)
    # init output transposed array
    data_array_t = [[0 for row in range(dimx)] for col in range(dimy)]
    # fill output transposed array
    for i in range(dimx):
        for j in range(dimy):
            if two_d:
                data_array_t[j][i] = data_array[i][j]
            else:
                data_array_t[j][i] = data_array[j]
    return data_array_t
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.