numpy
data manipulation
python
array slicing
column extraction

Extracting specific columns in numpy array

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Extracting specific columns from a NumPy array uses array indexing. For a 2D array, arr[:, col_index] extracts a single column, and arr[:, [col1, col2]] extracts multiple columns. The : selects all rows, and the second index selects columns. NumPy also supports boolean indexing and fancy indexing for more complex column selection patterns.

Single Column

python
1import numpy as np
2
3data = np.array([
4    [1, 2, 3, 4],
5    [5, 6, 7, 8],
6    [9, 10, 11, 12]
7])
8
9# Extract column 0 (first column)
10col0 = data[:, 0]
11print(col0)  # [1 5 9]
12
13# Extract column 2 (third column)
14col2 = data[:, 2]
15print(col2)  # [3 7 11]
16
17# Extract the last column
18last = data[:, -1]
19print(last)  # [4 8 12]

Note: data[:, 0] returns a 1D array of shape (3,). To keep it as a column vector (2D), use data[:, [0]] or data[:, 0:1].

Multiple Columns

python
1# Extract columns 0 and 2
2cols = data[:, [0, 2]]
3print(cols)
4# [[ 1  3]
5#  [ 5  7]
6#  [ 9 11]]
7
8# Extract columns 1, 3
9cols = data[:, [1, 3]]
10print(cols)
11# [[ 2  4]
12#  [ 6  8]
13#  [10 12]]
14
15# Reorder columns
16reordered = data[:, [3, 1, 0, 2]]
17print(reordered)
18# [[ 4  2  1  3]
19#  [ 8  6  5  7]
20#  [12 10  9 11]]

Column Range (Slicing)

python
1# Columns 1 through 3 (exclusive)
2cols = data[:, 1:3]
3print(cols)
4# [[ 2  3]
5#  [ 6  7]
6#  [10 11]]
7
8# First two columns
9first_two = data[:, :2]
10print(first_two)
11# [[1 2]
12#  [5 6]
13#  [9 10]]
14
15# Every other column
16every_other = data[:, ::2]
17print(every_other)
18# [[ 1  3]
19#  [ 5  7]
20#  [ 9 11]]

Boolean Column Selection

python
1# Select columns where the first row value is > 2
2mask = data[0] > 2
3print(mask)  # [False False  True  True]
4
5cols = data[:, mask]
6print(cols)
7# [[ 3  4]
8#  [ 7  8]
9#  [11 12]]
10
11# Select columns by name using a separate list
12col_names = ["age", "height", "weight", "score"]
13wanted = ["height", "score"]
14mask = np.isin(col_names, wanted)
15cols = data[:, mask]

Named Columns with Structured Arrays

python
1# Structured array with named fields
2dt = np.dtype([("name", "U10"), ("age", "i4"), ("score", "f4")])
3records = np.array([
4    ("Alice", 30, 95.5),
5    ("Bob", 25, 88.0),
6    ("Charlie", 35, 72.3)
7], dtype=dt)
8
9# Access by column name
10print(records["name"])   # ['Alice' 'Bob' 'Charlie']
11print(records["score"])  # [95.5 88.  72.3]
12
13# Multiple columns (returns structured array)
14subset = records[["name", "score"]]

Extracting Columns into Separate Variables

python
1data = np.array([
2    [1, 2, 3],
3    [4, 5, 6],
4    [7, 8, 9]
5])
6
7# Unpack columns
8col_a, col_b, col_c = data.T  # Transpose then unpack rows
9print(col_a)  # [1 4 7]
10print(col_b)  # [2 5 8]
11print(col_c)  # [3 6 9]
12
13# Or unpack specific columns
14x, y = data[:, 0], data[:, 1]

Views vs Copies

python
1data = np.array([[1, 2, 3], [4, 5, 6]])
2
3# Slicing returns a VIEW (shared memory)
4view = data[:, 1:3]
5view[0, 0] = 99
6print(data)  # [[1 99 3] [4  5 6]] — original modified!
7
8# Fancy indexing returns a COPY
9copy = data[:, [0, 2]]
10copy[0, 0] = 99
11print(data)  # [[1 99 3] [4  5 6]] — original unchanged
12
13# Force a copy from a slice
14safe = data[:, 1:3].copy()
15safe[0, 0] = 0
16print(data)  # Original unchanged

Performance with Large Arrays

python
1# For very large arrays, column access patterns matter
2large = np.random.randn(1000000, 100)
3
4# Row-major (C order, default): row access is fast, column access is slower
5# Column-major (Fortran order): column access is fast
6
7# If you mainly access columns, use Fortran order
8large_f = np.asfortranarray(large)
9col = large_f[:, 50]  # Faster column access

Common Pitfalls

  • Confusing data[:, 0] (1D) with data[:, [0]] (2D): Single index [:, 0] returns a 1D array of shape (n,). List index [:, [0]] returns a 2D column of shape (n, 1). This matters for operations that require 2D input like matrix multiplication.
  • Modifying a view and changing the original: Slice-based column extraction (data[:, 1:3]) returns a view. Modifying the view modifies the original array. Use .copy() if you need an independent copy.
  • Fancy indexing returning a copy: Unlike slicing, data[:, [0, 2]] returns a copy, not a view. Modifying the result does not affect the original. This inconsistency catches many people.
  • Using negative indices incorrectly: data[:, -1] gets the last column, but data[:, -1:] gets a 2D array with one column. The results have different shapes (1D vs 2D), which affects downstream operations.
  • Index out of bounds: data[:, 5] on a 4-column array raises IndexError. Check data.shape[1] before accessing columns by index, especially with dynamic data.

Summary

  • Use arr[:, col] for a single column and arr[:, [col1, col2]] for multiple columns
  • Use slicing arr[:, start:end] for column ranges
  • Boolean arrays can select columns based on conditions
  • Slicing creates views (shared memory); fancy indexing creates copies
  • Use .T (transpose) to unpack columns into separate variables
  • Check arr.shape[1] for the number of columns before indexing

Course illustration
Course illustration

All Rights Reserved.