Skip to content

Commit 81e6efd

Browse files
committed
Address bluss's comments and add iteration section
1 parent d07e0df commit 81e6efd

File tree

1 file changed

+92
-26
lines changed
  • src/doc/ndarray_for_numpy_users

1 file changed

+92
-26
lines changed

src/doc/ndarray_for_numpy_users/mod.rs

Lines changed: 92 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,29 @@
11
//! `ndarray` for NumPy users.
22
//!
3-
//! `ndarray`'s array type ([`ArrayBase`](../../struct.ArrayBase.html)), is
4-
//! very similar to NumPy's array type (`numpy.ndarray`):
3+
//! This is an introductory guide to `ndarray` for people with experience using
4+
//! NumPy, although it may also be useful to others. For a more general
5+
//! introduction to `ndarray`'s array type `ArrayBase`, see the [`ArrayBase`
6+
//! docs][ArrayBase].
7+
//!
8+
//! # Contents
9+
//!
10+
//! * [Similarities](#similarities)
11+
//! * [Some key differences](#some-key-differences)
12+
//! * [Other Rust array/matrix crates](#other-rust-arraymatrix-crates)
13+
//! * [Rough `ndarray`–NumPy equivalents](#rough-ndarraynumpy-equivalents)
14+
//!
15+
//! * [Array creation](#array-creation)
16+
//! * [Indexing and slicing](#indexing-and-slicing)
17+
//! * [Shape and strides](#shape-and-strides)
18+
//! * [Mathematics](#mathematics)
19+
//! * [Array manipulation](#array-manipulation)
20+
//! * [Iteration](#iteration)
21+
//! * [Convenience methods for 2-D arrays](#convenience-methods-for-2-d-arrays)
22+
//!
23+
//! # Similarities
24+
//!
25+
//! `ndarray`'s array type ([`ArrayBase`][ArrayBase]), is very similar to
26+
//! NumPy's array type (`numpy.ndarray`):
527
//!
628
//! * Arrays have a single element type.
729
//! * Arrays can have arbitrarily many dimensions.
@@ -47,14 +69,12 @@
4769
//! </td>
4870
//! <td>
4971
//!
50-
//! In `ndarray`, all arrays are instances of
51-
//! [`ArrayBase`](../../struct.ArrayBase.html), but `ArrayBase` is generic over
52-
//! the ownership of the data. [`Array`](../../type.Array.html) owns its data;
53-
//! [`ArrayView`](../../type.ArrayView.html) is a view;
54-
//! [`ArrayViewMut`](../../type.ArrayViewMut.html) is a mutable view; and
55-
//! [`ArcArray`](../../type.ArcArray.html) has a reference-counted pointer to
56-
//! its data (with copy-on-write mutation). Arrays and views follow Rust's
57-
//! aliasing rules.
72+
//! In `ndarray`, all arrays are instances of [`ArrayBase`][ArrayBase], but
73+
//! `ArrayBase` is generic over the ownership of the data. [`Array`][Array]
74+
//! owns its data; [`ArrayView`][ArrayView] is a view;
75+
//! [`ArrayViewMut`][ArrayViewMut] is a mutable view; and
76+
//! [`ArcArray`][ArcArray] has a reference-counted pointer to its data (with
77+
//! copy-on-write mutation). Arrays and views follow Rust's aliasing rules.
5878
//!
5979
//! </td>
6080
//! </tr>
@@ -68,9 +88,9 @@
6888
//! <td>
6989
//!
7090
//! In `ndarray`, you can create fixed-dimension arrays, such as
71-
//! [`Array2`](../../type.Array2.html). This takes advantage of the type system
72-
//! to help you write correct code and also avoids small heap allocations for
73-
//! the shape and strides.
91+
//! [`Array2`][Array2]. This takes advantage of the type system to help you
92+
//! write correct code and also avoids small heap allocations for the shape and
93+
//! strides.
7494
//!
7595
//! </td>
7696
//! </tr>
@@ -164,13 +184,14 @@
164184
//! `np.array([[1.,2.,3.], [4.,5.,6.]])` | [`array![[1.,2.,3.], [4.,5.,6.]]`][array!] or [`arr2(&[[1.,2.,3.], [4.,5.,6.]])`][arr2()] | 2×3 floating-point array literal
165185
//! `np.arange(0., 10., 0.5)` or `np.r_[:10.:0.5]` | [`Array::range(0., 10., 0.5)`][::range()] | create a 1-D array with values `0.`, `0.5`, …, `9.5`
166186
//! `np.linspace(0., 10., 11)` or `np.r_[:10.:11j]` | [`Array::linspace(0., 10., 11)`][::linspace()] | create a 1-D array with 11 elements with values `0.`, …, `10.`
187+
//! `np.ones((3, 4, 5))` | [`Array::ones((3, 4, 5))`][::ones()] | create a 3×4×5 array filled with ones (inferring the element type)
167188
//! `np.zeros((3, 4, 5))` | [`Array::zeros((3, 4, 5))`][::zeros()] | create a 3×4×5 array filled with zeros (inferring the element type)
168189
//! `np.zeros((3, 4, 5), order='F')` | [`Array::zeros((3, 4, 5).f())`][::zeros()] | create a 3×4×5 array with Fortran (column-major) memory layout filled with zeros (inferring the element type)
190+
//! `np.zeros_like(a, order='C')` | [`Array::zeros(a.raw_dim())`][::zeros()] | create an array of zeros of the shape shape as `a`, with row-major memory layout (unlike NumPy, this infers the element type from context instead of duplicating `a`'s element type)
169191
//! `np.full((3, 4), 7.)` | [`Array::from_elem((3, 4), 7.)`][::from_elem()] | create a 3×4 array filled with the value `7.`
170192
//! `np.eye(3)` | [`Array::eye(3)`][::eye()] | create a 3×3 identity matrix (inferring the element type)
171193
//! `np.array([1, 2, 3, 4]).reshape((2, 2))` | [`Array::from_shape_vec((2, 2), vec![1, 2, 3, 4])?`][::from_shape_vec()] | create a 2×2 array from the elements in the list/`Vec`
172194
//! `np.array([1, 2, 3, 4]).reshape((2, 2), order='F')` | [`Array::from_shape_vec((2, 2).f(), vec![1, 2, 3, 4])?`][::from_shape_vec()] | create a 2×2 array from the elements in the list/`Vec` using Fortran (column-major) order
173-
//! `np.empty((3, 4))` | [`unsafe { Array::uninitialized((3, 4)) }`][::uninitialized()] | create a 3×4 uninitialized array (inferring the element type)
174195
//! `np.random` | See the [`ndarray-rand`](https://crates.io/crates/ndarray-rand) crate. | create arrays of random numbers
175196
//!
176197
//! ## Indexing and slicing
@@ -190,22 +211,30 @@
190211
//!
191212
//! NumPy | `ndarray` | Notes
192213
//! ------|-----------|------
193-
//! `a[-1]` | [`a[a.len()-1]`][.index()] | access the last element in 1-D array `a`
194-
//! `a[1,4]` | [`a[(1,4)]`][.index()] | access the element in row 1, column 4
195-
//! `a[1]` or `a[1,:,:]` | [`a.slice(s![1, .., ..])`][.slice()] or [`a.subview(Axis(0), 1)`][.subview()] | get a 2-D subview of a 3-D array at index 1 of axis 0
196-
//! `a[0:5]` or `a[:5]` or `a[0:5,:]` | [`a.slice(s![0..5, ..])`][.slice()] or [`a.slice(s![..5, ..])`][.slice()] or [`a.slice_axis(Axis(0), (0..5).into())`][.slice_axis()] | get the first 5 rows of a 2-D array
197-
//! `a[-5:]` or `a[-5:,:]` | [`a.slice(s![-5.., ..])`][.slice()] or [`a.slice_axis(Axis(0), (-5..).into())`][.slice_axis()] | get the last 5 rows of a 2-D array
198-
//! `a[:3,4:9]` | [`a.slice(s![..3, 4..9])`][.slice()] | columns 4, 5, 6, 7, and 8 of the first 3 rows
199-
//! `a[1:4:2,::-1]` | [`a.slice(s![1..4;2, ..;-1])`][.slice()] | rows 1 and 3 with the columns in reverse order
214+
//! `a[-1]` | [`a[a.len() - 1]`][.index()] | access the last element in 1-D array `a`
215+
//! `a[1, 4]` | [`a[[1, 4]]`][.index()] | access the element in row 1, column 4
216+
//! `a[1]` or `a[1, :, :]` | [`a.slice(s![1, .., ..])`][.slice()] or [`a.subview(Axis(0), 1)`][.subview()] | get a 2-D subview of a 3-D array at index 1 of axis 0
217+
//! `a[0:5]` or `a[:5]` or `a[0:5, :]` | [`a.slice(s![0..5, ..])`][.slice()] or [`a.slice(s![..5, ..])`][.slice()] or [`a.slice_axis(Axis(0), Slice::from(0..5))`][.slice_axis()] | get the first 5 rows of a 2-D array
218+
//! `a[-5:]` or `a[-5:, :]` | [`a.slice(s![-5.., ..])`][.slice()] or [`a.slice_axis(Axis(0), Slice::from(-5..))`][.slice_axis()] | get the last 5 rows of a 2-D array
219+
//! `a[:3, 4:9]` | [`a.slice(s![..3, 4..9])`][.slice()] | columns 4, 5, 6, 7, and 8 of the first 3 rows
220+
//! `a[1:4:2, ::-1]` | [`a.slice(s![1..4;2, ..;-1])`][.slice()] | rows 1 and 3 with the columns in reverse order
200221
//!
201222
//! ## Shape and strides
202223
//!
224+
//! Note that [`a.shape()`][.shape()], [`a.dim()`][.dim()], and
225+
//! [`a.raw_dim()`][.raw_dim()] all return the shape of the array, but as
226+
//! different types. `a.shape()` returns the shape as `&[Ix]`, (where
227+
//! [`Ix`][Ix] is `usize`) which is useful for general operations on the shape.
228+
//! `a.dim()` returns the shape as `D::Pattern`, which is useful for
229+
//! pattern-matching shapes. `a.raw_dim()` returns the shape as `D`, which is
230+
//! useful for creating other arrays of the same shape.
231+
//!
203232
//! NumPy | `ndarray` | Notes
204233
//! ------|-----------|------
205234
//! `np.ndim(a)` or `a.ndim` | [`a.ndim()`][.ndim()] | get the number of dimensions of array `a`
206235
//! `np.size(a)` or `a.size` | [`a.len()`][.len()] | get the number of elements in array `a`
207236
//! `np.shape(a)` or `a.shape` | [`a.shape()`][.shape()] or [`a.dim()`][.dim()] | get the shape of array `a`
208-
//! `a.shape[axis]` | [`a.len_of(Axis(axis))`][.len_of()] or `a.shape()[axis]` | get the length of an axis
237+
//! `a.shape[axis]` | [`a.len_of(Axis(axis))`][.len_of()] | get the length of an axis
209238
//! `a.strides` | [`a.strides()`][.strides()] | get the strides of array `a`
210239
//! `np.size(a) == 0` or `a.size == 0` | [`a.is_empty()`][.is_empty()] | check if the array has zero elements
211240
//!
@@ -242,7 +271,7 @@
242271
//!
243272
//! </td><td>
244273
//!
245-
//! transpose of array `a`
274+
//! transpose of array `a` (view for `.t()` or by-move for `.reversed_axes()`)
246275
//!
247276
//! </td></tr>
248277
//!
@@ -467,11 +496,33 @@
467496
//! `a[:] = b` | [`a.assign(&b)`][.assign()] | copy the data from array `b` into array `a`
468497
//! `np.concatenate((a,b), axis=1)` | [`stack![Axis(1), a, b]`][stack!] or [`stack(Axis(1), &[a.view(), b.view()])`][stack()] | concatenate arrays `a` and `b` along axis 1
469498
//! `a[:,np.newaxis]` or `np.expand_dims(a, axis=1)` | [`a.insert_axis(Axis(1))`][.insert_axis()] | create an array from `a`, inserting a new axis 1
470-
//! `a.transpose()` or `a.T` | [`a.t()`][.t()] or [`a.reversed_axes()`][.reversed_axes()] | transpose of array `a`
499+
//! `a.transpose()` or `a.T` | [`a.t()`][.t()] or [`a.reversed_axes()`][.reversed_axes()] | transpose of array `a` (view for `.t()` or by-move for `.reversed_axes()`)
471500
//! `np.diag(a)` | [`a.diag()`][.diag()] | view the diagonal of `a`
472-
//! `a.flat` | [`a.iter()`][.iter()] | iterator over the array elements in logical order
473501
//! `a.flatten()` | [`Array::from_iter(a.iter())`][::from_iter()] | create a 1-D array by flattening `a`
474502
//!
503+
//! ## Iteration
504+
//!
505+
//! `ndarray` has lots of interesting iterators/producers that implement the
506+
//! [`NdProducer`][NdProducer] trait, which is a generalization of `Iterator`
507+
//! to multiple dimensions. This makes it possible to correctly and efficiently
508+
//! zip together slices/subviews of arrays in multiple dimensions with
509+
//! [`Zip`][Zip] or [`azip!()`][azip!]. The purpose of this is similar to
510+
//! [`np.nditer`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.nditer.html),
511+
//! but [`Zip`][Zip] is implemented and used somewhat differently.
512+
//!
513+
//! This table lists some of the iterators/producers which have a direct
514+
//! equivalent in NumPy. For a more complete introduction to producers and
515+
//! iterators, see [*Loops, Producers, and
516+
//! Iterators*](../../struct.ArrayBase.html#loops-producers-and-iterators).
517+
//! Note that there are also variants of these iterators (with a `_mut` suffix)
518+
//! that yield `ArrayViewMut` instead of `ArrayView`.
519+
//!
520+
//! NumPy | `ndarray` | Notes
521+
//! ------|-----------|------
522+
//! `a.flat` | [`a.iter()`][.iter()] | iterator over the array elements in logical order
523+
//! `np.ndenumerate(a)` | [`a.indexed_iter()`][.indexed_iter()] | flat iterator yielding the index along with each element reference
524+
//! `iter(a)` | [`a.outer_iter()`][.outer_iter()] or [`a.axis_iter(Axis(0))`][.axis_iter()] | iterator over the first (outermost) axis, yielding each subview
525+
//!
475526
//! ## Convenience methods for 2-D arrays
476527
//!
477528
//! NumPy | `ndarray` | Notes
@@ -483,9 +534,17 @@
483534
//! `a.shape[0] == a.shape[1]` | [`a.is_square()`][.is_square()] | check if the array is square
484535
//!
485536
//! [.all_close()]: ../../struct.ArrayBase.html#method.all_close
486-
//! [array!]: ../../macro.array.html
537+
//! [ArcArray]: ../../type.ArcArray.html
487538
//! [arr2()]: ../../fn.arr2.html
539+
//! [array!]: ../../macro.array.html
540+
//! [Array]: ../../type.Array.html
541+
//! [Array2]: ../../type.Array2.html
542+
//! [ArrayBase]: ../../struct.ArrayBase.html
543+
//! [ArrayView]: ../../type.ArrayView.html
544+
//! [ArrayViewMut]: ../../type.ArrayViewMut.html
488545
//! [.assign()]: ../../struct.ArrayBase.html#method.assign
546+
//! [.axis_iter()]: ../../struct.ArrayBase.html#method.axis_iter
547+
//! [azip!]: ../../macro.azip.html
489548
//! [.cols()]: ../../struct.ArrayBase.html#method.cols
490549
//! [.column()]: ../../struct.ArrayBase.html#method.column
491550
//! [.column_mut()]: ../../struct.ArrayBase.html#method.column_mut
@@ -503,10 +562,12 @@
503562
//! [::from_shape_vec_unchecked()]: ../../struct.ArrayBase.html#method.from_shape_vec_unchecked
504563
//! [::from_vec()]: ../../struct.ArrayBase.html#method.from_vec
505564
//! [.index()]: ../../struct.ArrayBase.html#impl-Index<I>
565+
//! [.indexed_iter()]: ../../struct.ArrayBase.html#method.indexed_iter
506566
//! [.insert_axis()]: ../../struct.ArrayBase.html#method.insert_axis
507567
//! [.is_empty()]: ../../struct.ArrayBase.html#method.is_empty
508568
//! [.is_square()]: ../../struct.ArrayBase.html#method.is_square
509569
//! [.iter()]: ../../struct.ArrayBase.html#method.iter
570+
//! [Ix]: ../../type.Ix.html
510571
//! [.len()]: ../../struct.ArrayBase.html#method.len
511572
//! [.len_of()]: ../../struct.ArrayBase.html#method.len_of
512573
//! [::linspace()]: ../../struct.ArrayBase.html#method.linspace
@@ -519,7 +580,11 @@
519580
//! [matrix-* dot]: ../../struct.ArrayBase.html#method.dot-1
520581
//! [.mean_axis()]: ../../struct.ArrayBase.html#method.mean_axis
521582
//! [.ndim()]: ../../struct.ArrayBase.html#method.ndim
583+
//! [NdProducer]: ../../trait.NdProducer.html
584+
//! [::ones()]: ../../struct.ArrayBase.html#method.ones
585+
//! [.outer_iter()]: ../../struct.ArrayBase.html#method.outer_iter
522586
//! [::range()]: ../../struct.ArrayBase.html#method.range
587+
//! [.raw_dim()]: ../../struct.ArrayBase.html#method.raw_dim
523588
//! [.reversed_axes()]: ../../struct.ArrayBase.html#method.reversed_axes
524589
//! [.row()]: ../../struct.ArrayBase.html#method.row
525590
//! [.row_mut()]: ../../struct.ArrayBase.html#method.row_mut
@@ -542,3 +607,4 @@
542607
//! [vec-* dot]: ../../struct.ArrayBase.html#method.dot
543608
//! [.visit()]: ../../struct.ArrayBase.html#method.visit
544609
//! [::zeros()]: ../../struct.ArrayBase.html#method.zeros
610+
//! [Zip]: ../../struct.Zip.html

0 commit comments

Comments
 (0)