The core data structure in numpy is the `ndarray`

(short for *n*-dimensional array). `ndarray`

s are

- homogeneous (i.e. they contain items of the same data-type)
- contain items of fixed sizes (given by a
*shape*, a tuple of*n*positive integers that specify the sizes of each dimension)

One-dimensional array:

```
x = np.arange(15)
# array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
x.shape
# (15,)
```

Two-dimensional array:

```
x = np.asarray([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14]])
x
# array([[ 0, 1, 2, 3, 4],
# [ 5, 6, 7, 8, 9],
# [10, 11, 12, 13, 14]])
x.shape
# (3, 5)
```

Three-dimensional:

```
np.arange(12).reshape([2,3,2])
```

To initialize an array without specifying its contents use:

```
x = np.empty([2, 2])
# array([[ 0., 0.],
# [ 0., 0.]])
```

**Datatype guessing and automatic casting**

The data-type is set to float by default

```
x = np.empty([2, 2])
# array([[ 0., 0.],
# [ 0., 0.]])
x.dtype
# dtype('float64')
```

If some data is provided, numpy will guess the data-type:

```
x = np.asarray([[1, 2], [3, 4]])
x.dtype
# dtype('int32')
```

Note that when doing assignments numpy will attempt to automatically cast values to suit the `ndarray`

's datatype

```
x[1, 1] = 1.5 # assign a float value
x[1, 1]
# 1
# value has been casted to int
x[1, 1] = 'z' # value cannot be casted, resulting in a ValueError
```

**Array broadcasting**

See also Broadcasting array operations.

```
x = np.asarray([[1, 2], [3, 4]])
# array([[1, 2],
[3, 4]])
y = np.asarray([[5, 6]])
# array([[5, 6]])
```

In matrix terminology, we would have a 2x2 matrix and a 1x2 row vector. Still we're able to do a sum

```
# x + y
array([[ 6, 8],
[ 8, 10]])
```

This is because the array `y`

is "*stretched*" to:

```
array([[5, 6],
[5, 6]])
```

to suit the shape of `x`

.

**Resources:**

- Introduction to the ndarray from the official documentation: The N-dimensional array (ndarray)
- Class reference: ndarray.