Tôi có đoạn mã sau:
r = numpy.zeros(shape = (width, height, 9))
Nó tạo ra một width x height x 9
ma trận chứa đầy số không. Thay vào đó, tôi muốn biết liệu có một chức năng hoặc cách để khởi tạo chúng thay vào NaN
đó một cách dễ dàng.
Tôi có đoạn mã sau:
r = numpy.zeros(shape = (width, height, 9))
Nó tạo ra một width x height x 9
ma trận chứa đầy số không. Thay vào đó, tôi muốn biết liệu có một chức năng hoặc cách để khởi tạo chúng thay vào NaN
đó một cách dễ dàng.
Câu trả lời:
Bạn hiếm khi cần các vòng lặp cho các hoạt động vector trong numpy. Bạn có thể tạo một mảng chưa được khởi tạo và gán cho tất cả các mục cùng một lúc:
>>> a = numpy.empty((3,3,))
>>> a[:] = numpy.nan
>>> a
array([[ NaN, NaN, NaN],
[ NaN, NaN, NaN],
[ NaN, NaN, NaN]])
Tôi đã hẹn giờ thay thế a[:] = numpy.nan
ở đây và a.fill(numpy.nan)
như được đăng bởi Blaenk:
$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)"
10000 loops, best of 3: 54.3 usec per loop
$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a[:] = np.nan"
10000 loops, best of 3: 88.8 usec per loop
Thời gian hiển thị một ưu tiên cho ndarray.fill(..)
sự thay thế nhanh hơn. OTOH, tôi thích triển khai tiện lợi của numpy khi bạn có thể gán giá trị cho toàn bộ lát cắt tại thời điểm đó, ý định của mã rất rõ ràng.
Lưu ý rằng ndarray.fill
thực hiện hoạt động tại chỗ của nó, numpy.empty((3,3,)).fill(numpy.nan)
thay vào đó sẽ trở lại None
.
a = numpy.empty((3, 3,)) * numpy.nan
. Nó hẹn giờ nhanh hơn fill
nhưng chậm hơn phương thức gán, nhưng nó là một oneliner !!
.fill()
phương pháp này, nhưng sự khác biệt về tốc độ giảm xuống thực tế không có gì khi các mảng trở nên lớn hơn.
np.empty([2, 5])
tạo một mảng, sau đó fill()
sửa đổi mảng đó tại chỗ, nhưng không trả về một bản sao hoặc một tham chiếu. Nếu bạn muốn gọi np.empty(2, 5)
bằng một tên ("gán cho một biến"), bạn phải làm như vậy trước khi bạn thực hiện các thao tác tại chỗ trên nó. Điều tương tự sẽ xảy ra nếu bạn làm [1, 2, 3].insert(1, 4)
. Danh sách được tạo và 4 được chèn, nhưng không thể có được một tham chiếu đến danh sách (và do đó nó có thể được coi là đã được thu gom rác). Trên dữ liệu không thay đổi như chuỗi, một bản sao được trả về, vì bạn không thể vận hành tại chỗ. Gấu trúc có thể làm cả hai.
Một tùy chọn khác là sử dụng numpy.full
, một tùy chọn có sẵn trong NumPy 1.8+
a = np.full([height, width, 9], np.nan)
Điều này khá linh hoạt và bạn có thể điền nó với bất kỳ số nào khác mà bạn muốn.
full
có nghĩa là gì. np.empy((x,y))*np.nan
là một người chạy tốt (và khả năng tương thích cho các phiên bản cũ của numpy).
fill
python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)" 100000 loops, best of 3: 13.3 usec per loop python -mtimeit "import numpy as np; a = np.full((100,100), np.nan);" 100000 loops, best of 3: 18.5 usec per loop
python -mtimeit "import numpy as np; a = np.empty((1000,1000)); a.fill(np.nan)" 1000 loops, best of 3: 381 usec per loop $ python -mtimeit "import numpy as np; a = np.full((1000,1000), np.nan);" 1000 loops, best of 3: 383 usec per loop
Tôi đã so sánh các phương án được đề xuất cho tốc độ và thấy rằng, đối với các vectơ / ma trận đủ lớn để điền vào, tất cả các phương án ngoại trừ val * ones
và array(n * [val])
đều nhanh như nhau.
Mã để tái tạo cốt truyện:
import numpy
import perfplot
val = 42.0
def fill(n):
a = numpy.empty(n)
a.fill(val)
return a
def colon(n):
a = numpy.empty(n)
a[:] = val
return a
def full(n):
return numpy.full(n, val)
def ones_times(n):
return val * numpy.ones(n)
def list(n):
return numpy.array(n * [val])
perfplot.show(
setup=lambda n: n,
kernels=[fill, colon, full, ones_times, list],
n_range=[2 ** k for k in range(20)],
logx=True,
logy=True,
xlabel="len(a)",
)
numpy.full(n, val)
là chậm hơn so với a = numpy.empty(n) .. a.fill(val)
vì nó làm điều tương tự trong nội bộ
Bạn có quen thuộc với numpy.nan
không?
Bạn có thể tạo phương thức của riêng bạn, chẳng hạn như:
def nans(shape, dtype=float):
a = numpy.empty(shape, dtype)
a.fill(numpy.nan)
return a
Sau đó
nans([3,4])
sẽ xuất
array([[ NaN, NaN, NaN, NaN],
[ NaN, NaN, NaN, NaN],
[ NaN, NaN, NaN, NaN]])
Tôi tìm thấy mã này trong một chủ đề danh sách gửi thư .
Bạn luôn có thể sử dụng phép nhân nếu bạn không nhớ lại ngay lập tức .empty
hoặc .full
các phương thức:
>>> np.nan * np.ones(shape=(3,2))
array([[ nan, nan],
[ nan, nan],
[ nan, nan]])
Tất nhiên nó cũng hoạt động với bất kỳ giá trị số nào khác:
>>> 42 * np.ones(shape=(3,2))
array([[ 42, 42],
[ 42, 42],
[ 42, 42]])
Nhưng câu trả lời được chấp nhận của @ u0b34a0f6ae nhanh hơn gấp 3 lần (chu kỳ CPU, không phải chu kỳ não để ghi nhớ cú pháp numpy;):
$ python -mtimeit "import numpy as np; X = np.empty((100,100));" "X[:] = np.nan;"
100000 loops, best of 3: 8.9 usec per loop
(predict)laneh@predict:~/src/predict/predict/webapp$ master
$ python -mtimeit "import numpy as np; X = np.ones((100,100));" "X *= np.nan;"
10000 loops, best of 3: 24.9 usec per loop
Một cách khác là numpy.broadcast_to(val,n)
trả về trong thời gian không đổi bất kể kích thước và cũng là bộ nhớ hiệu quả nhất (nó trả về một khung nhìn của phần tử lặp lại). Thông báo trước là giá trị trả về là chỉ đọc.
Dưới đây là so sánh hiệu suất của tất cả các phương pháp khác đã được đề xuất bằng cách sử dụng cùng một tiêu chuẩn như trong câu trả lời của Nico Schlömer .
Như đã nói, numpy.empty () là con đường để đi. Tuy nhiên, đối với các đối tượng, fill () có thể không thực hiện chính xác những gì bạn nghĩ:
In[36]: a = numpy.empty(5,dtype=object)
In[37]: a.fill([])
In[38]: a
Out[38]: array([[], [], [], [], []], dtype=object)
In[39]: a[0].append(4)
In[40]: a
Out[40]: array([[4], [4], [4], [4], [4]], dtype=object)
Một cách xung quanh có thể là:
In[41]: a = numpy.empty(5,dtype=object)
In[42]: a[:]= [ [] for x in range(5)]
In[43]: a[0].append(4)
In[44]: a
Out[44]: array([[4], [], [], [], []], dtype=object)
Một khả năng khác chưa được đề cập ở đây là sử dụng lát NumPy:
a = numpy.tile(numpy.nan, (3, 3))
Cũng cho
array([[ NaN, NaN, NaN],
[ NaN, NaN, NaN],
[ NaN, NaN, NaN]])
Tôi không biết về so sánh tốc độ.
np.nan
đi sai khi chuyển đổi sang int.