{
"cells": [
{
"cell_type": "markdown",
"id": "163b5a5f",
"metadata": {},
"source": [
"# Saving and sharing your NumPy arrays\n",
"\n",
"## What you'll learn\n",
"\n",
"You'll save your NumPy arrays as zipped files and human-readable\n",
"comma-delimited files i.e. \\*.csv. You will also learn to load both of these\n",
"file types back into NumPy workspaces.\n",
"\n",
"## What you'll do\n",
"\n",
"You'll learn two ways of saving and reading files--as compressed and as\n",
"text files--that will serve most of your storage needs in NumPy.\n",
"\n",
"* You'll create two 1D arrays and one 2D array\n",
"* You'll save these arrays to files\n",
"* You'll remove variables from your workspace\n",
"* You'll load the variables from your saved file\n",
"* You'll compare zipped binary files to human-readable delimited files\n",
"* You'll finish with the skills of saving, loading, and sharing NumPy arrays\n",
"\n",
"\n",
"## What you'll need\n",
"\n",
"* NumPy\n",
"* read-write access to your working directory\n",
"\n",
"Load the necessary functions using the following command."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "e849a8f2",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np"
]
},
{
"cell_type": "markdown",
"id": "11cd18b7",
"metadata": {},
"source": [
"In this tutorial, you will use the following Python, IPython magic, and NumPy functions:\n",
"\n",
"* [`np.arange`](https://numpy.org/doc/stable/reference/generated/numpy.arange.html)\n",
"* [`np.savez`](https://numpy.org/doc/stable/reference/generated/numpy.savez.html)\n",
"* [`del`](https://docs.python.org/3/reference/simple_stmts.html#del)\n",
"* [`whos`](https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-whos)\n",
"* [`np.load`](https://numpy.org/doc/stable/reference/generated/numpy.load.html)\n",
"* [`np.block`](https://numpy.org/doc/stable/reference/generated/numpy.block.html)\n",
"* [`np.newaxis`](https://numpy.org/doc/stable/reference/constants.html?highlight=newaxis#numpy.newaxis)\n",
"* [`np.savetxt`](https://numpy.org/doc/stable/reference/generated/numpy.savetxt.html)\n",
"* [`np.loadtxt`](https://numpy.org/doc/stable/reference/generated/numpy.loadtxt.html)"
]
},
{
"cell_type": "markdown",
"id": "0d18085f",
"metadata": {},
"source": [
"---\n",
"\n",
"## Create your arrays\n",
"\n",
"Now that you have imported the NumPy library, you can make a couple of\n",
"arrays; let's start with two 1D arrays, `x` and `y`, where `y =\n",
"x**2`.You\n",
"will assign `x` to the integers from 0 to 9 using\n",
"[`np.arange`](https://numpy.org/doc/stable/reference/generated/numpy.arange.html)."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "ccb9fce5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0 1 2 3 4 5 6 7 8 9]\n",
"[ 0 1 4 9 16 25 36 49 64 81]\n"
]
}
],
"source": [
"x = np.arange(10)\n",
"y = x ** 2\n",
"print(x)\n",
"print(y)"
]
},
{
"cell_type": "markdown",
"id": "c60998b1",
"metadata": {},
"source": [
"## Save your arrays with NumPy's [`savez`](https://numpy.org/doc/stable/reference/generated/numpy.savez.html?highlight=savez#numpy.savez)\n",
"\n",
"Now you have two arrays in your workspace,\n",
"\n",
"`x: [0 1 2 3 4 5 6 7 8 9]`\n",
"\n",
"`y: [ 0 1 4 9 16 25 36 49 64 81]`\n",
"\n",
"The first thing you will do is save them to a file as zipped arrays\n",
"using\n",
"[`savez`](https://numpy.org/doc/stable/reference/generated/numpy.savez.html?highlight=savez#numpy.savez).\n",
"You will use two options to label the arrays in the file,\n",
"\n",
"1. `x_axis = x`: this option is assigning the name `x_axis` to the variable `x`\n",
"2. `y_axis = y`: this option is assigning the name `y_axis` to the variable `y`"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "d6f4e89c",
"metadata": {},
"outputs": [],
"source": [
"np.savez(\"x_y-squared.npz\", x_axis=x, y_axis=y)"
]
},
{
"cell_type": "markdown",
"id": "b29e24ae",
"metadata": {},
"source": [
"## Remove the saved arrays and load them back with NumPy's [`load`](https://numpy.org/doc/stable/reference/generated/numpy.load.html#numpy.load)\n",
"\n",
"In your current working directory, you should have a new file with the\n",
"name `x_y-squared.npz`. This file is a zipped binary of the two arrays,\n",
"`x` and `y`. Let's clear the workspace and load the values back in. This\n",
"`x_y-squared.npz` file contains two [NPY\n",
"format](https://numpy.org/doc/stable/reference/generated/numpy.lib.format.html#module-numpy.lib.format)\n",
"files. The NPY format is a [native binary\n",
"format](https://en.wikipedia.org/wiki/Binary_file). You cannot read\n",
"the numbers in a standard text editor or spreadsheet.\n",
"\n",
"1. remove `x` and `y` from the workspaec with [`del`](https://docs.python.org/3/reference/simple_stmts.html#del)\n",
"2. load the arrays into the workspace in a dictionary with [`np.load`](https://numpy.org/doc/stable/reference/generated/numpy.load.html#numpy.load)\n",
"\n",
"To see what variables are in the workspace, use the Jupyter/IPython\n",
"\"magic\" command\n",
"[`whos`](https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-whos)."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "de181ebb",
"metadata": {},
"outputs": [],
"source": [
"del x, y"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "98469ffe",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Variable Type Data/Info\n",
"------------------------------\n",
"np module kages/numpy/__init__.py'>\n"
]
}
],
"source": [
"%whos"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "80a5bdec",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['x_axis', 'y_axis']\n"
]
}
],
"source": [
"load_xy = np.load(\"x_y-squared.npz\")\n",
"\n",
"print(load_xy.files)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "169d1671",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Variable Type Data/Info\n",
"-------------------------------\n",
"load_xy NpzFile NpzFile 'x_y-squared.npz'<...>with keys: x_axis, y_axis\n",
"np module kages/numpy/__init__.py'>\n"
]
}
],
"source": [
"whos"
]
},
{
"cell_type": "markdown",
"id": "9b1683e5",
"metadata": {},
"source": [
"## Reassign the NpzFile arrays to `x` and `y`\n",
"\n",
"You've now created the dictionary with an `NpzFile`-type. The\n",
"included files are `x_axis` and `y_axis` that you defined in your\n",
"`savez` command. You can reassign `x` and `y` to the `load_xy` files."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "9afabe94",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0 1 2 3 4 5 6 7 8 9]\n",
"[ 0 1 4 9 16 25 36 49 64 81]\n"
]
}
],
"source": [
"x = load_xy[\"x_axis\"]\n",
"y = load_xy[\"y_axis\"]\n",
"print(x)\n",
"print(y)"
]
},
{
"cell_type": "markdown",
"id": "33a6a2d7",
"metadata": {},
"source": [
"## Success\n",
"You have created, saved, deleted, and loaded the variables `x` and `y` using `savez` and `load`. Nice work.\n",
"\n",
"## Another option: saving to human-readable csv\n",
"Let's consider another scenario, you want to share `x` and `y` with\n",
"other people or other programs. You may need human-readable text file\n",
"that is easier to share. Next, you use the\n",
"[`savetxt`](https://numpy.org/doc/stable/reference/generated/numpy.savetxt.html#numpy.savetxt)\n",
"to save `x` and `y` in a comma separated value file, `x_y-squared.csv`.\n",
"The resulting csv is composed of ASCII characters. You can load the file\n",
"back into NumPy or read it with other programs.\n",
"\n",
"## Rearrange the data into a single 2D array\n",
"First, you have to create a single 2D array from your two 1D arrays. The\n",
"csv-filetype is a spreadsheet-style dataset. The csv arranges numbers in\n",
"rows--separated by new lines--and columns--separated by commas. If the\n",
"data is more complex e.g. multiple 2D arrays or higher dimensional\n",
"arrays, it is better to use `savez`. Here, you use\n",
"two NumPy functions to format the data:\n",
"\n",
"1. [`np.block`](https://numpy.org/doc/stable/reference/generated/numpy.block.html?highlight=block#numpy.block): this function appends arrays together into a 2D array\n",
"\n",
"2. [`np.newaxis`](https://numpy.org/doc/stable/reference/constants.html?highlight=newaxis#numpy.newaxis): this function forces the 1D array into a 2D column vector with 10 rows and 1 column."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "3bd7312c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"the output array has shape (10, 2) with values:\n",
"[[ 0 0]\n",
" [ 1 1]\n",
" [ 2 4]\n",
" [ 3 9]\n",
" [ 4 16]\n",
" [ 5 25]\n",
" [ 6 36]\n",
" [ 7 49]\n",
" [ 8 64]\n",
" [ 9 81]]\n"
]
}
],
"source": [
"array_out = np.block([x[:, np.newaxis], y[:, np.newaxis]])\n",
"print(\"the output array has shape \", array_out.shape, \" with values:\")\n",
"print(array_out)"
]
},
{
"cell_type": "markdown",
"id": "f7198db8",
"metadata": {},
"source": [
"## Save the data to csv file using [`savetxt`](https://numpy.org/doc/stable/reference/generated/numpy.savetxt.html#numpy.savetxt)\n",
"\n",
"You use `savetxt` with a three options to make your file easier to read:\n",
"\n",
"* `X = array_out`: this option tells `savetxt` to save your 2D array, `array_out`, to the file `x_y-squared.csv`\n",
"* `header = 'x, y'`: this option writes a header before any data that labels the columns of the csv\n",
"* `delimiter = ','`: this option tells `savetxt` to place a comma between each column in the file"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "571876da",
"metadata": {},
"outputs": [],
"source": [
"np.savetxt(\"x_y-squared.csv\", X=array_out, header=\"x, y\", delimiter=\",\")"
]
},
{
"cell_type": "markdown",
"id": "14c1cd4e",
"metadata": {},
"source": [
"Open the file, `x_y-squared.csv`, and you'll see the following:\n",
"\n",
"```\n",
"# x, y\n",
"0.000000000000000000e+00,0.000000000000000000e+00\n",
"1.000000000000000000e+00,1.000000000000000000e+00\n",
"2.000000000000000000e+00,4.000000000000000000e+00\n",
"3.000000000000000000e+00,9.000000000000000000e+00\n",
"4.000000000000000000e+00,1.600000000000000000e+01\n",
"5.000000000000000000e+00,2.500000000000000000e+01\n",
"6.000000000000000000e+00,3.600000000000000000e+01\n",
"7.000000000000000000e+00,4.900000000000000000e+01\n",
"8.000000000000000000e+00,6.400000000000000000e+01\n",
"9.000000000000000000e+00,8.100000000000000000e+01\n",
"```\n",
"\n",
"## Our arrays as a csv file\n",
"\n",
"There are two features that you shoud notice here:\n",
"\n",
"1. NumPy uses `#` to ignore headings when using `loadtxt`. If you're using\n",
"[`loadtxt`](https://numpy.org/doc/stable/reference/generated/numpy.loadtxt.html)\n",
"with other csv files, you can skip header rows with `skiprows =\n",
"`.\n",
"2. The integers were written in scientific notation. _You can_ specify\n",
"the format of the text using the `savetxt` option, [`fmt =\n",
"`](https://docs.python.org/3/library/string.html#formatstrings), but it\n",
"will still be written with ASCII characters. In general, you cannot\n",
"preserve the type of ASCII numbers as `float` or `int`.\n",
"\n",
"\n",
"Now, delete `x` and `y` again and assign them to your columns in `x-y_squared.csv`."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "48fdde24",
"metadata": {},
"outputs": [],
"source": [
"del x, y"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "f1143eee",
"metadata": {},
"outputs": [],
"source": [
"load_xy = np.loadtxt(\"x_y-squared.csv\", delimiter=\",\")"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "76353206",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(10, 2)"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"load_xy.shape"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "ddd3623e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]\n",
"[ 0. 1. 4. 9. 16. 25. 36. 49. 64. 81.]\n"
]
}
],
"source": [
"x = load_xy[:, 0]\n",
"y = load_xy[:, 1]\n",
"print(x)\n",
"print(y)"
]
},
{
"cell_type": "markdown",
"id": "65a731af",
"metadata": {},
"source": [
"## Success, but remember your types\n",
"\n",
"When you saved the arrays to the csv file, you did not preserve the\n",
"`int` type. When loading the arrays back into your workspace the default process will be to load the csv file as a 2D floating point array e.g. `load_xy.dtype == 'float64'` and `load_xy.shape == (10, 2)`."
]
},
{
"cell_type": "markdown",
"id": "2e3251a8",
"metadata": {},
"source": [
"## Wrapping up\n",
"\n",
"In conclusion, you can create, save, and load arrays in NumPy. Saving arrays makes sharing your work and collaboration much easier. There are other ways Python can save data to files, such as [pickle](https://docs.python.org/3/library/pickle.html), but `savez` and `savetxt` will serve most of your storage needs for future NumPy work and sharing with other people, respectively.\n",
"\n",
"__Next steps__: you can import data with missing values from [Importing with genfromtext](https://numpy.org/devdocs/user/basics.io.genfromtxt.html) or learn more about general NumPy IO with [Reading and Writing Files](https://numpy.org/devdocs/user/how-to-io.html)."
]
}
],
"metadata": {
"jupytext": {
"text_representation": {
"extension": ".md",
"format_name": "myst",
"format_version": 0.13,
"jupytext_version": "1.11.1"
}
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.13"
},
"source_map": [
12,
42,
44,
58,
70,
75,
93,
95,
115,
119,
123,
129,
131,
139,
144,
170,
174,
184,
186,
221,
225,
229,
233,
238,
245
]
},
"nbformat": 4,
"nbformat_minor": 5
}