horizental = row
vertiacl = column
matrix= row*column
dimensions are called axes
.shape = tuple of array dimensions
[1, 2, 1]
, has one axis
length=no of elements = 3 in [1,2,3]
NumPy’s array class is called ndarray alias array
attributes of ndarray
- ndarray.ndim = no of axes
- ndarray.shape = matrix with n rows and m columns, shape will be (n,m). length of the shape tuple is therefore the number of axes, ndim
- ndarray.size = the total number of elements of the array. This is equal to the product of the elements of shape.
- ndarray.dtype = an object describing the type of the elements in the array. One can create or specify dtype’s using standard Python types. Additionally NumPy provides types of its own. ex: numpy.int32, numpy.int16, and numpy.float64
- ndarray.itemsize = the size in bytes of each element of the array. For example, an array of elements of type float64 has itemsize 8 (=64/8), while one of type complex32 has itemsize 4 (=32/8). It is equivalent to ndarray.dtype.itemsize.
- ndarray.data = the buffer containing the actual elements of the array. Normally, we won’t need to use this attribute because we will access the elements in an array using indexing facilities.
- example:
- -----------------------------------------------------------------------------------
- >>>import numpy as np
- >>>a= np.arange(15).reshape(3, 5)
>>>a - array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]]) - >>>a.ndim
- 2
- >>> a.dtype.name
'int64' - >>> a.itemsize
8 - >>> a.size
15 - >>> type(a)
<class 'numpy.ndarray'> - -----------------------------------------------------------------------------------
Array Creation/conversion
https://numpy.org/doc/stable/reference/generated/numpy.array.html#numpy-array
syntax :
- numpy.array(object, dtype=None, *, copy=True, order='K', subok=False, ndmin=0, like=None)
-
- using numpy array() function which takes single sequence as an argument.
-
- b = np.array([6, 7, 8])
one_dim_array = np.array([1.2, 2.4, 3.5, 4.7, 6.1, 7.2, 8.3, 9.5])
- array transforms sequences of sequences into two-dimensional arrays, sequences of sequences of sequences into three-dimensional arrays, and so on.
- Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
two_dim_array = np.array([[6, 5], [11, 7], [4, 8]])
The type of the array can also be explicitly specified at creation time:
>>> c = np.array([[1, 2], [3, 4]], dtype=complex)
>>> c array([[1.+0.j, 2.+0.j], [3.+0.j, 4.+0.j]])
If you are not careful with dtype
assignments, you can get unwanted overflow, as such
a = np.array([127, 128, 129], dtype=np.int8)
An 8-bit signed integer represents integers from -128 to 127.
Assigning the int8
array to integers outside of this range results
in overflow.
a = np.array([2, 3, 4], dtype=np.uint32)
b = np.array([5, 6, 7], dtype=np.uint32)
c_unsigned32 = a - b
c_signed32 = a - b.astype(np.int32)
The default NumPy behavior is to create arrays in either 32 or 64-bit signed integers (platform dependent and matches C int size) or double precision floating point numbers, int32/int64 and float, respectively.
Array creating function
https://numpy.org/doc/stable/reference/routines.array-creation.html#routines-array-creation
1 - 1D array creation functions
The 1D array creation functions e.g. numpy.linspace
and
numpy.arange
generally need at least two inputs, start
and
stop
.
To create sequences of numbers, NumPy provides the arange
function
which is analogous to the Python built-in range
, but returns an
array.
arange (start,end,step)
start=included end= not included
>>> np.arange(0, 2, 0.3) ##can use floating step value range cant use float
array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])
When arange is used with floating point arguments, it is generally not possible to predict the number of elements
obtained, due to the finite floating point precision. For this reason, it is usually better to use the function
linspace that receives as an argument the number of elements that we want, instead of the step:
numpy.arange([start, ]stop, [step, ]dtype=None, *, like=None)
np.arange(10)
Note: best practice fornumpy.arange
is to use integer start, end, and step values. There are some subtleties regardingdtype
. In the second example, thedtype
is defined. In the third example, the array isdtype=float
to accommodate the step size of0.1
. Due to roundoff error, thestop
value is sometimes included.
numpy.linspace
will create arrays with a specified number of elements, and
spaced equally between the specified beginning and end values. For
example:
np.linspace(1., 4., 6)
The advantage of this creation function is that you guarantee the number of elements and the starting and end point. The previousarange(start, stop, step)
will not include the valuestop
.
from numpy import pi ## or use np.pi>>> np.linspace(0, 2, 9) array([0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ])x = np.linspace(0, 2 * pi, 100)f = np.sin(x) see also
array
,
zeros
,
zeros_like
,
ones
,
ones_like
,
empty
,
empty_like
,
arange
,
linspace
,
numpy.random.Generator.rand,
numpy.random.Generator.randn,
fromfunction
,
fromfile
2D array creation functions
The 2D array creation functions e.g.numpy.eye
,numpy.diag
, andnumpy.vander
define properties of special matrices represented as 2D arrays.
np.eye(n, m)
defines a 2D identity matrix. The elements where i=j (row index and column index are equal) are 1
and the rest are 0, as such:
>>>np.eye(3) array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]]) >>>np.eye(3, 5) array([[1., 0., 0., 0., 0.], [0., 1., 0., 0., 0.], [0., 0., 1., 0., 0.]])
numpy.diag
can define either a square 2D array with given values along
the diagonal or if given a 2D array returns a 1D array that is
only the diagonal elements. The two array creation functions can be helpful while
doing linear algebra, as such:
numpy.diag(v, k=0)[source]
- Parameters:
- varray_like
If v is a 2-D array, return a copy of its k-th diagonal. If v is a 1-D array, return a 2-D array with v on the k-th diagonal.
- kint, optional
Diagonal in question. The default is 0. Use k>0 for diagonals above the main diagonal, and k<0 for diagonals below the main diagonal.
np.diag([1, 2, 3]) array([[1, 0, 0], [0, 2, 0], [0, 0, 3]]) np.diag([1, 2, 3], 1) array([[0, 1, 0, 0], [0, 0, 2, 0], [0, 0, 0, 3], [0, 0, 0, 0]]) a = np.array([[1, 2], [3, 4]]) np.diag(a) array([1, 4])
vander(x, n)
defines a Vandermonde matrix as a 2D NumPy array. Each column
of the Vandermonde matrix is a decreasing power of the input 1D array or
list or tuple,
x
where the highest polynomial order is n-1
. This array creation
routine is helpful in generating linear least squares models, as such:
general ndarray creation functions
The ndarray creation functions e.g. numpy.ones
,
numpy.zeros
, and random
define
arrays based upon the desired shape. The ndarray creation functions
can create arrays with any dimension by specifying how many dimensions
and length along that dimension in a tuple or list.
The function zeros
creates an array full of zeros, the function
ones
creates an array full of ones, and the function empty
creates an array whose initial content is random and depends on the
state of the memory. By default, the dtype of the created array is
float64
, but it can be specified via the key word argument dtype
.
>>> np.zeros((3, 4))
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
>>> np.zeros((3, 4),dtype=int)
array([[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]])
>>> np.ones((2, 3, 4), dtype=np.int16)
array([[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]],
[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]]], dtype=int16)
>>> np.empty((2, 3))
array([[6.90389397e-310, 7.48156888e-317, 0.00000000e+000],
[0.00000000e+000, 0.00000000e+000, 0.00000000e+000]])
random
method of the result of
default_rng
will create an array filled with random
values between 0 and 1. It is included with the numpy.random
library. Below, two arrays are created with shapes (2,3) and (2,3,2),
respectively. The seed is set to 42 so you can reproduce these
pseudorandom numbers:syntax numpy.random.randint(low, high=None, size=None, dtype=int)
interval [low, high)
random_integers_between_50_and_100 = np.random.randint(low=50, high=101, size=(6))
using generator uses Permuted Congruential Generator (PCG64)
rng = np.random.default_rng(seed=42)
rng.random()
rng = np.random.default_rng(12345)
rng.integers(low=0, high=10, size=3)
random_sample
to ease forward-porting to the new random API.generates random floats in interval (-2,2)
from numpy.random import default_rng
default_rng(42).random((2,3))
array([[0.77395605, 0.43887844, 0.85859792], [0.69736803, 0.09417735, 0.97562235]])
default_rng(42).random((2,3,2))
array([[[0.77395605, 0.43887844], [0.85859792, 0.69736803], [0.09417735, 0.97562235]], [[0.7611397 , 0.78606431], [0.12811363, 0.45038594], [0.37079802, 0.92676499]]])
numpy.indices
will create a set of arrays (stacked as a one-higher
dimensioned array), one per dimension with each representing variation in that
dimension:
np.indices((3,3))
array([[[0, 0, 0], [1, 1, 1], [2, 2, 2]], [[0, 1, 2], [0, 1, 2], [0, 1, 2]]])
Printing Arrays
the last axis is printed from left to right,
the second-to-last is printed from top to bottom,
the rest are also printed from top to bottom, with each slice separated from the next by an empty line.If an array is too large to be printed, NumPy automatically skips the central part of the array and only prints the corners:
If an array is too large to be printed, NumPy automatically skips the central part of the array and only prints the corners:
>>> print(np.arange(10000))
[ 0 1 2 ... 9997 9998 9999]
>>> print(np.arange(10000).reshape(100, 100))
[[ 0 1 2 ... 97 98 99]
[ 100 101 102 ... 197 198 199]
[ 200 201 202 ... 297 298 299]
...
[9700 9701 9702 ... 9797 9798 9799]
[9800 9801 9802 ... 9897 9898 9899]
[9900 9901 9902 ... 9997 9998 9999]]
To disable this behaviour and force NumPy to print the entire array, you
can change the printing options using set_printoptions
.
>>>np.set_printoptions(threshold=sys.maxsize) # sys module should be imported
Operations
Arithmetic operators on arrays apply elementwise. A new array is created and filled with the result.
try
a = np.array([20, 30, 40, 50])
b = np.arange(4)
c = a - b
b**2
10 * np.sin(a)
a < 35
Unlike in many matrix languages, the product operator *
operates
elementwise in NumPy arrays. The matrix product can be performed using
the @
operator (in python >=3.5) or the dot
function or method:
>>> A = np.array([[1, 1],[0, 1]])
>>> B = np.array([[2, 0], [3, 4]])
>>> A * B
array([[2, 0],
[0, 4]])
>>> A @ B
array([[5, 4],
[3, 4]])
>>> A.dot(B)
array([[5, 4],
[3, 4]])
Some operations, such as +=
and *=
, act in place to modify an
existing array rather than create a new one.
rg = np.random.default_rng(1) # create instance of default random number generator
>>> rg
Generator(PCG64) at 0x7F16E6EDF680
>>> a = np.ones((2, 3), dtype=int)
b = rg.random((2, 3))
a *= 3
array([[3, 3, 3], [3, 3, 3]])
b += a
a += b # b is not automatically converted to integer type
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
numpy.core._exceptions._UFuncOutputCastingError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
When operating with arrays of different types, the type of the resulting array corresponds to the more general or precise one (a behavior known as upcasting).
src:
https://numpy.org/devdocs/user/quickstart.html
https://colab.research.google.com/github/google/eng-edu/blob/main/ml/cc/exercises/numpy_ultraquick_tutorial.ipynb
https://numpy.org/doc/stable/reference/random/generated/numpy.random.random_sample.html#numpy.random.random_sample
https://pandas.pydata.org/
Comments
Post a Comment