Khởi tạo mảng NumPy (điền các giá trị giống hệt nhau)


237

Tôi cần tạo một mảng NumPy có độ dài n, mỗi phần tử là v.

Có điều gì tốt hơn:

a = empty(n)
for i in range(n):
    a[i] = v

Tôi biết zerosonessẽ làm việc cho v = 0, 1. Tôi có thể sử dụng v * ones(n), nhưng nó sẽ không hoạt động khi vNone, và cũng sẽ chậm hơn nhiều.


1
Trên máy tính của tôi, đối với trường hợp 0, sử dụng a = np.zeros(n)trong vòng lặp nhanh hơn a.fill(0). Điều này trái ngược với những gì tôi mong đợi vì tôi nghĩ a=np.zeros(n)sẽ cần phân bổ và khởi tạo bộ nhớ mới. Nếu bất cứ ai có thể giải thích điều này, tôi sẽ đánh giá cao nó.
dùng3731622

Bạn không thể đặt nonein một mảng numpy, vì các ô được tạo với một kiểu dữ liệu cụ thể trong khi Không có kiểu riêng của nó và thực tế là một con trỏ.
Camion

@Camion Vâng tôi biết ngay bây giờ :) Tất nhiên v * ones(n)vẫn còn kinh khủng, vì nó sử dụng phép nhân đắt tiền. Thay thế *bằng +mặc dù, và v + zeros(n)hóa ra là tốt đáng ngạc nhiên trong một số trường hợp ( stackoverflow.com/questions/5891410/ ích ).
tối đa

max, thay vì tạo một mảng bằng 0 trước khi thêm v, thậm chí còn nhanh hơn để tạo nó trống var = np.empty(n)và sau đó điền nó với 'var [:] = v'. (btw, np.full()nhanh như thế này)
Camion

Câu trả lời:


308

NumPy 1.8 giới thiệu np.full(), mà là một phương pháp trực tiếp hơn empty()tiếp theo fill()để tạo một mảng đầy với một giá trị nhất định:

>>> np.full((3, 5), 7)
array([[ 7.,  7.,  7.,  7.,  7.],
       [ 7.,  7.,  7.,  7.,  7.],
       [ 7.,  7.,  7.,  7.,  7.]])

>>> np.full((3, 5), 7, dtype=int)
array([[7, 7, 7, 7, 7],
       [7, 7, 7, 7, 7],
       [7, 7, 7, 7, 7]])

Đây được cho là những cách để tạo ra một mảng đầy giá trị nhất định, vì nó rõ ràng mô tả những gì đang đạt được (và nó có thể về nguyên tắc là rất hiệu quả vì nó thực hiện một nhiệm vụ rất cụ thể).


1
Phương thức đầy đủ () này hoạt động tốt với tôi nhưng tôi không thể tìm thấy một chút tài liệu cho nó. Bất cứ ai có thể chỉ cho tôi đến đúng nơi?
James Adams

1
Bạn ít nhất có thể làm help(numpy.full)trong một vỏ Python. Tôi cũng ngạc nhiên rằng nó không có trong tài liệu web.
Eric O Lebigot

Trên hệ thống của tôi (Python 2.7, Numpy 1.8), np.full () thực sự chậm hơn một chút so với np.empty () theo sau là np.fill ().
John Zwinck

1
Đối với 10.000 yếu tố, tôi quan sát điều tương tự (ngoại trừ điều np.fill()đó không tồn tại và nên có arr.fill()), với sự khác biệt khoảng 10%. Nếu sự khác biệt là lớn hơn, tôi sẽ nêu ra một vấn đề trong trình theo dõi lỗi NumPy. :) Tôi thích mã rõ ràng hơn và rõ ràng hơn, vì một sự khác biệt nhỏ như vậy trong thời gian thực hiện, vì vậy tôi đi với np.full()tất cả thời gian.
Eric O Lebigot

Trên máy của tôi, np.full () có cùng tốc độ với np.array.fill ()
Fnord

92

Đã cập nhật cho Numpy 1.7.0: (Hat-tip cho @Rolf Bartstra.)

a=np.empty(n); a.fill(5) là nhanh nhất

Theo thứ tự tốc độ giảm dần:

%timeit a=np.empty(1e4); a.fill(5)
100000 loops, best of 3: 5.85 us per loop

%timeit a=np.empty(1e4); a[:]=5 
100000 loops, best of 3: 7.15 us per loop

%timeit a=np.ones(1e4)*5
10000 loops, best of 3: 22.9 us per loop

%timeit a=np.repeat(5,(1e4))
10000 loops, best of 3: 81.7 us per loop

%timeit a=np.tile(5,[1e4])
10000 loops, best of 3: 82.9 us per loop

13
Thêm thời gian cho gần đây và trực tiếp np.full()sẽ hữu ích. Trên máy của tôi, với NumPy 1.8.1, nó chậm hơn khoảng 15% so với fill()phiên bản ít trực tiếp hơn (điều này thật bất ngờ, vì full()có khả năng đi nhanh hơn một chút).
Eric O Lebigot

@DavidSanders: Tôi không chắc chắn tôi đang theo dõi bạn: fill()là giải pháp nhanh nhất. Các giải pháp nhân chậm hơn nhiều.
Eric O Lebigot

2
Lưu ý: nếu tốc độ thực sự là một mối quan tâm, sử dụng kích thước 10000thay vì 1e4tạo ra sự khác biệt đáng chú ý, vì một số lý do ( full()chậm hơn gần 50%, với 1e4).
Eric O Lebigot

Chỉ cần thêm kết quả của tôi vào full(), nó chạy chậm hơn đáng kể khi kiểu dữ liệu rõ ràng không phải là dấu phẩy. Mặt khác, nó có thể so sánh (nhưng chậm hơn một chút) với các phương pháp tốt nhất ở đây.
dùng2699

@ user2699 Tôi không quan sát này, với 100.000 yếu tố: full(100000, 5), full(100000, 5, dtype=float), full(100000, 5, dtype=int)a =np.empty(100000); a.fill(5)tất cả mất khoảng cùng thời gian trên máy tính của tôi (không có bộ nhớ đệm: %timeit -r1 -n1 …) (NumPy 1.11.2).
Eric O Lebigot

65

Tôi tin filllà cách nhanh nhất để làm điều này.

a = np.empty(10)
a.fill(7)

Bạn cũng nên luôn luôn tránh lặp đi lặp lại như bạn đang làm trong ví dụ của bạn. Một đơn giản a[:] = vsẽ thực hiện những gì lặp đi lặp lại của bạn bằng cách sử dụng phát sóng numpy .


1
Cảm ơn bạn. Nhìn vào fill, tôi thấy rằng repeatphù hợp với nhu cầu của tôi thậm chí còn tốt hơn.
tối đa

Bạn có nhớ cập nhật câu trả lời của bạn để nói rằng đề xuất của bạn a[:]=vthực sự nhanh hơn tổng thể so với fill?
tối đa

@max Có nhanh hơn không? Phát sóng là một cách tổng quát hơn để điền vào một mảng và tôi đoán là chậm hơn hoặc bằng với trường hợp sử dụng rất hẹp của fill.
Paul

16

Rõ ràng, không chỉ tốc độ tuyệt đối mà cả thứ tự tốc độ (theo báo cáo của người dùng1579844) đều phụ thuộc vào máy; đây là những gì tôi tìm thấy:

a=np.empty(1e4); a.fill(5) là nhanh nhất;

Theo thứ tự tốc độ giảm dần:

timeit a=np.empty(1e4); a.fill(5) 
# 100000 loops, best of 3: 10.2 us per loop
timeit a=np.empty(1e4); a[:]=5
# 100000 loops, best of 3: 16.9 us per loop
timeit a=np.ones(1e4)*5
# 100000 loops, best of 3: 32.2 us per loop
timeit a=np.tile(5,[1e4])
# 10000 loops, best of 3: 90.9 us per loop
timeit a=np.repeat(5,(1e4))
# 10000 loops, best of 3: 98.3 us per loop
timeit a=np.array([5]*int(1e4))
# 1000 loops, best of 3: 1.69 ms per loop (slowest BY FAR!)

Vì vậy, hãy thử và tìm hiểu, và sử dụng những gì nhanh nhất trên nền tảng của bạn.


14

Tôi đã có

numpy.array(n * [value])

trong tâm trí, nhưng rõ ràng là chậm hơn tất cả các đề xuất khác đủ lớn n .

Dưới đây là so sánh đầy đủ với perfplot (một dự án thú cưng của tôi).

nhập mô tả hình ảnh ở đây

Hai emptylựa chọn thay thế vẫn là nhanh nhất (với NumPy 1.12.1). fullbắt kịp cho các mảng lớn.


Mã để tạo cốt truyện:

import numpy as np
import perfplot


def empty_fill(n):
    a = np.empty(n)
    a.fill(3.14)
    return a


def empty_colon(n):
    a = np.empty(n)
    a[:] = 3.14
    return a


def ones_times(n):
    return 3.14 * np.ones(n)


def repeat(n):
    return np.repeat(3.14, (n))


def tile(n):
    return np.repeat(3.14, [n])


def full(n):
    return np.full((n), 3.14)


def list_to_array(n):
    return np.array(n * [3.14])


perfplot.show(
    setup=lambda n: n,
    kernels=[empty_fill, empty_colon, ones_times, repeat, tile, full, list_to_array],
    n_range=[2 ** k for k in range(27)],
    xlabel="len(a)",
    logx=True,
    logy=True,
)

7

Bạn có thể sử dụng numpy.tile, ví dụ:

v = 7
rows = 3
cols = 5
a = numpy.tile(v, (rows,cols))
a
Out[1]: 
array([[7, 7, 7, 7, 7],
       [7, 7, 7, 7, 7],
       [7, 7, 7, 7, 7]])

Mặc dù tilecó nghĩa là 'gạch' một mảng (thay vì vô hướng, như trong trường hợp này), nó sẽ thực hiện công việc, tạo các mảng được điền sẵn ở bất kỳ kích thước và kích thước nào.


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.