Python NumPy Arrays
Table of Contents + β
In the last lesson, Introduction to NumPy, you saw what an array is and why it is fast. So you can already make a simple array and do math on it. Now comes the real skill. You need to build arrays in different shapes, peek inside them, and pull out exactly the values you want. Without that, an array is just a box you cannot open. This lesson teaches you how to open it.
π€ Why learn the array in detail?
In real data work, you rarely type out every number by hand. Sometimes you need a row of a thousand zeros to start with. Sometimes your data is a grid, like rows and columns in a spreadsheet, not a flat line. And once you have the data, you almost always want a small piece of it, not the whole thing.
So you need a few skills:
- Build arrays quickly without typing every value.
- Understand the arrayβs shape, which is how many rows and columns it has.
- Grab one value, or a slice of values, out of the array.
- Change the shape when the data needs to be arranged differently.
Letβs go through each one with small examples you can run.
π§± Different ways to create an array
You already know np.array() from a list. But NumPy gives you faster ways to build common arrays without typing every number.
This snippet shows the handy array builders side by side:
import numpy as np
zeros = np.zeros(5) # five zerosones = np.ones(3) # three onesrng = np.arange(0, 10, 2) # start at 0, stop before 10, step by 2even_grid = np.full((2, 3), 7) # a 2 by 3 grid, every value is 7
print(zeros)print(ones)print(rng)print(even_grid)Output
[0. 0. 0. 0. 0.][1. 1. 1.][0 2 4 6 8][[7 7 7] [7 7 7]]Letβs read each builder:
np.zeros(5)makes an array of five zeros. You often start with zeros and fill in real values later.np.ones(3)is the same idea but filled with ones.np.arange(0, 10, 2)works like Pythonβsrange. It starts at 0, stops before 10, and steps by 2. So you get 0, 2, 4, 6, 8.np.full((2, 3), 7)makes a grid with 2 rows and 3 columns, every slot set to 7. The(2, 3)is the shape.
Note
Notice the zeros and ones print with a dot, like 0. and 1.. That dot means they are decimal (float) numbers, not whole numbers. np.zeros and np.ones give floats by default.
π Shape and dimensions
An array can be a flat line of numbers, or a grid, or even deeper. NumPy uses a few words to describe this, and they show up everywhere.
This example builds a flat array and a grid, then asks each one about itself:
import numpy as np
flat = np.array([1, 2, 3, 4])grid = np.array([[1, 2, 3], [4, 5, 6]])
print(flat.shape, flat.ndim)print(grid.shape, grid.ndim)print(grid.size)Output
(4,) 1(2, 3) 26Here is what those words mean:
shapetells you the size along each direction.flatis(4,), meaning four values in a single row.gridis(2, 3), meaning 2 rows and 3 columns.ndimis the number of dimensions. A flat row is 1 dimension. A grid of rows and columns is 2 dimensions.sizeis the total count of values. The grid has 2 rows times 3 columns, so 6 values.
A simple way to picture it: a 1D array is a single shelf of items. A 2D array is a full bookcase with several shelves stacked up.
π― Indexing: getting one value
Reaching into an array works like reaching into a list. You use square brackets with a position, and counting starts at 0.
For a flat array, you give one number, the position:
import numpy as np
prices = np.array([10, 20, 30, 40, 50])
print(prices[0]) # first valueprint(prices[2]) # third valueprint(prices[-1]) # last valueOutput
103050For a 2D grid, you give two numbers: the row first, then the column. NumPy lets you put both inside one pair of brackets, separated by a comma.
import numpy as np
grid = np.array([[1, 2, 3], [4, 5, 6]])
print(grid[0, 0]) # row 0, column 0print(grid[1, 2]) # row 1, column 2print(grid[0]) # the whole first rowOutput
16[1 2 3]So grid[1, 2] means βgo to row 1, then column 2β. Remember both counts start at 0, so row 1 is the second row and column 2 is the third one. And if you give just one number like grid[0], you get the whole first row back as its own array.
βοΈ Slicing: getting a range of values
A slice pulls out a range of values instead of just one. The shape is start:stop, where stop is not included, just like list slicing in Python.
This pulls different ranges out of a flat array:
import numpy as np
nums = np.array([10, 20, 30, 40, 50, 60])
print(nums[1:4]) # positions 1, 2, 3print(nums[:3]) # from the start up to position 3print(nums[3:]) # from position 3 to the endOutput
[20 30 40][10 20 30][40 50 60]The same idea works on a grid. You slice the rows and the columns at the same time, separated by a comma:
import numpy as np
grid = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(grid[0:2, 1:3]) # first two rows, columns 1 and 2Output
[[2 3] [5 6]]Reading grid[0:2, 1:3]: the part before the comma slices the rows (0 and 1), and the part after slices the columns (1 and 2). So you carve out a small box from inside the grid. This is how you grab, say, a few rows and a few columns out of a big table.
π Reshaping an array
Sometimes the data is in one shape but you need another. reshape rearranges the same values into a new shape, without changing the values themselves.
This takes a flat row of six numbers and lays it out as a 2 by 3 grid:
import numpy as np
nums = np.arange(1, 7) # [1 2 3 4 5 6]grid = nums.reshape(2, 3) # 2 rows, 3 columns
print(grid)Output
[[1 2 3] [4 5 6]]The one rule to remember: the new shape must hold the same number of values. You have 6 numbers, so reshape(2, 3) works because 2 times 3 is 6. Asking for reshape(2, 4) would need 8 values and NumPy would raise an error.
Caution
If the counts do not match, you get ValueError: cannot reshape array of size 6 into shape (2,4). Always check that the rows times the columns equals the total number of values.
π Quick reference
Here are the array tools from this lesson in one place.
| What you want | The code |
|---|---|
| An array of zeros | np.zeros(5) |
| A range with a step | np.arange(0, 10, 2) |
| Rows and columns count | arr.shape |
| One value in a grid | grid[row, col] |
| A range of values | arr[1:4] |
| Rearrange into a new shape | arr.reshape(2, 3) |
β οΈ Common Mistakes
A few traps that catch people early:
- Forgetting that counting starts at 0. The first row is
grid[0], notgrid[1]. Asking for a position that does not exist gives anIndexError.
prices = np.array([10, 20, 30])
# β There is no position 3 in a 3-item arrayprint(prices[3]) # IndexError: index 3 is out of bounds
# β
The last item is at position 2, or use -1print(prices[2]) # 30print(prices[-1]) # 30- Expecting
stopto be included in a slice.nums[1:4]gives positions 1, 2, and 3, but not 4. The stop point is left out. - Reshaping into a shape that does not fit. The rows times the columns must equal the total number of values, or NumPy raises a
ValueError.
β Best Practices
Habits that keep array work smooth:
- Print
arr.shapewhenever you are unsure what an array looks like. It is the fastest way to understand your data. - Use the builders like
np.zerosandnp.arangeinstead of typing long lists by hand. Less typing, fewer mistakes. - Slice instead of looping. If you want part of an array, a slice like
arr[1:4]is faster and clearer than a loop that copies values. - For a grid, write the index as
grid[row, col]rather thangrid[row][col]. Both work, but the comma form is the NumPy way and reads better.
π§© What Youβve Learned
β
You can build arrays fast with np.zeros, np.ones, np.arange, and np.full.
β
shape tells you the rows and columns, ndim tells you the number of dimensions, and size is the total count of values.
β
Indexing with arr[i] or grid[row, col] gets one value, and counting starts at 0.
β
Slicing with arr[start:stop] gets a range, and the stop point is not included.
β
reshape rearranges the same values into a new shape, as long as the counts match.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What does grid.shape return for an array with 2 rows and 3 columns?
Why: shape lists the size along each direction, rows first then columns, so a 2-row, 3-column grid has shape (2, 3).
- 2
What does np.arange(0, 10, 2) produce?
Why: arange starts at 0, steps by 2, and stops before 10, so you get 0, 2, 4, 6, 8. The stop value 10 is not included.
- 3
For nums = np.array([10, 20, 30, 40, 50]), what is nums[1:4]?
Why: A slice goes from start up to but not including stop, so positions 1, 2, and 3 give [20 30 40].
- 4
You have a flat array of 6 numbers. Which reshape will work?
Why: The new shape must hold the same number of values. 2 times 3 is 6, which matches, so reshape(2, 3) works while the others do not.
π Whatβs Next?
Now you can build, shape, and slice arrays with ease. But raw arrays of numbers only take you so far. Next we meet Pandas, the tool that turns rows and columns into a friendly table you can label, search, and analyze.