# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # 01 - Introduction to numpy

# ## Why NumPy?
#
# In general you should use [numpy](https://numpy.org/) library if you want to do fancy things with **numbers**, especially if you have **matrices** or **arrays.** 
#
# NumPy is at the center of scientific Python ecosystem and it is a work-horse of many scientific libraries including scikit-learn, scikit-image, matplotlib, SciPy,...
#
# ## Import
#
# To use NumPy we need to start python interpreter and import the `numpy` package:

import numpy as np

# ## NumPy Array
#
# - __array:__ 
# Homogeneous multidimensional data container with all elements of the same type. 
#
# It is similar to Python lists, but it's specialised for working on numerical data. 

# Let's create a simple numpy array from a Python list by using [`np.array`](https://numpy.org/doc/stable/reference/generated/numpy.array.html):

x = np.array([2, 1, 5])
print(x)

# ### Lists vs Numpy arrays
#
# The Python core library provides Lists. A list is the Python equivalent of an array, but it is resizeable and can contain elements of different types.
#
# Pros of an array:
#  - **Size** - Numpy data structures take up less space
#  - **Performance** - faster than lists
#  - **Functionality** - SciPy and NumPy have optimized functions such as linear algebra operations built in.

L = range(1000)
# %timeit [i**2 for i in L]

# [__np.arange__](https://numpy.org/doc/stable/reference/generated/numpy.arange.html) works like Python built-in [range](https://docs.python.org/3/library/stdtypes.html#range), but it returns a numpy array: 

np.arange(5)

a = np.arange(1000)
# %timeit a**2

# ### Memory layout
#
# NumPy array is just a memory block with extra information how to interpret its contents.
#
# ### Array creation
#
# To construct an array with pre-defined elements we can also use other built-in helper functions:

# [__np.ones__](https://numpy.org/doc/stable/reference/generated/numpy.ones.html) and [__np.zeros__](https://numpy.org/doc/stable/reference/generated/numpy.zeros.html) return arrays of 0s and 1s, respectively: 

np.ones(5)

np.zeros(5)

# [__np.random.rand__](https://numpy.org/doc/stable/reference/random/generated/numpy.random.rand.html) creates an array of random numbers from a uniform distribution over [0, 1):

np.random.rand(5)

# We can also construct a two- or more dimensional arrays:

np.array([[1, 2], [5, 6]])

np.ones((2, 2))

# Alternatively, an n-dimensional array can be obtained by reshaping a 1-D array:

a = np.arange(12)
a.reshape((4,3))

# Previous: [00 - Index](../01-numpy-introduction.ipynb)<span style="float:right;">Next: [02 - Working with a dataset](02_dataset_intro.ipynb)</span>

StarcoderdataJupyterScriptsDedupFiltered