# NumPy Multidimensional Array - ndarray

NumPy is a library that uses multidimensional arrays as the basic data structure. The only data structure in NumPy is `ndarray` but not Python primitive `list` data type, because `list` runs relatively slowly.

After you have learned `ndarray` that is cornerstone of NumPy, you will understand why NumPy can achieve high-speed computing.

## ndarray Definition

`ndarray` is the abbreviation of n-dimension array, or in other words - multidimensional arrays. `ndarray` is an array object representing a multidimensional, homogeneous array of fixed-size items.

The dimensions and the number of elements are defined by the shape, that is a tuple of N integers that represents the number of elements in each dimension. The element type in the array is defined by `dtype`- `data-type object`.

Let’s explain the sentences above in layman language. All the elements stored in the `ndarray` object must have the same data type and size.

The characteristics of `ndarray` data type are summarized as follows.

1. Can only store elements of the same type
2. The amount of data in each dimension must be the same, for example 2D `ndarray` must have the same amount of elements in every column, and of course also in each row.
3. It is written in C language and it could execute matrix operation optimally

## ndarray Attributes

Let’s list the attributes of `ndarray`.

Attributes Description
`T` Transpose matrix. When the array is 1 D, the original array is returned.
`data` A Python buffer object that points to the starting position of the data in the array.
`dtype` The data type of the element contained in the ndarray.
`flags` Information about how to store ndarray data in memory (memory layout).
`flat` An iterator that converts ndarray to a one-dimensional array.
`imag` The imaginary part of ndarray data
`real` Real part of ndarray data
`size` The number of elements contained in the ndarray.
`itemsize` The size of each element in bytes.
`nbytes` The total memory (in bytes) occupied by the ndarray.
`ndim` The number of dimensions contained in the ndarray.
`shape` The shape of the ndarray (results are tuples).
`strides` The number of bytes required to move to the next adjacent element in each dimension direction is represented by a tuple.
`ctypes` An iterator that is processed in the ctypes module.
`base` The object on which ndarray is based (which memory is being referenced).

When you access the attributes of `ndarray`, the data of `ndarray` instance is not modified, even if when you use `.T` to get the transpose of the object. You get a new `ndarray` object but not modified original data.

Let’s take a look at the specific meaning of each attribute through example codes.

``````>>> import numpy as np
>>> a = np.array([1, 2, 3])
``````

We need to import `numpy` library and create a new 1-D array. You could check its data type and the data type of its element.

``````>>> type(a)
numpy.ndarray
>>> a.dtype
dtype('int32')
``````

Let’s create a new 2-D array and then check its attributes.

``````>>> b = np.array([[4, 5, 6], [7, 8, 9]])
>>> b
array([[4, 5, 6],
[7, 8, 9]])
>>> b.T     # get the transpose of b
array([[4, 7],
[5, 8],
[6, 9]])
>>> b       # b keeps unmodified
array([[4, 5, 6],
[7, 8, 9]])
>>> a.size  # a has 3 elements
3
>>> b.size  # b has 6 elements
6
>>> a.itemsize # The size of element in a. The data type here is int64 - 8 bytes
8
>>> b.nbytes  # check how many bytes in b. It is 48， where 6x8 = 48
48
>>> b.shape # The shape of b
(2, 3)
>>> b.dnim # The dimensions of b
2
``````