Readers often start from searches like numpy column_stack, numpy hstack, or combining two arrays column-wise—not the phrase “combine two column matrices.” In practice you usually have two equal-length lists or 1-D arrays and want one 2-D array with two columns (shape (n, 2)). This page centers on that intent: the right NumPy APIs, how 1-D inputs differ from column vectors (n, 1), row-wise vs column-wise stacking, and a short decision guide. For labeled tables, see pandas DataFrame.
Tested on: Python 3.13.3; NumPy 2.2.3; kernel 6.14.0-37-generic.
Quick answer: two 1-D sequences as two columns
For two equal-length 1-D sequences, prefer numpy.column_stack: it treats each input as a column of a single 2-D array.
import numpy as np
x = np.array([1, 2, 3])
y = np.array([10, 20, 30])
m = np.column_stack((x, y))
print(m.shape)
print(m)You should see shape (3, 2) and a matrix with x in the first column and y in the second.
What “two columns” means and how shapes line up
You might have:
- two Python lists of numbers,
- two 1-D
ndarrayvalues with shape(n,)(one number per row conceptually), or - two column vectors with shape
(n, 1).
The goal is usually a single 2-D array with shape (n, 2): n rows and two columns. Every column must have the same length n; otherwise stacking fails with a dimension mismatch.
Plain lists are not ndarray objects. Functions such as np.column_stack accept array-like inputs and return a NumPy array. You can pass lists directly or wrap with np.asarray for clarity.
Build two columns: column_stack, stack, hstack, concatenate
numpy.column_stack (best default for two 1-D inputs)
column_stack stacks 1-D arrays as columns into a 2-D array. It matches the common “two features side by side” pattern.
import numpy as np
a = [1, 2, 3]
b = [4, 5, 6]
print(np.column_stack((a, b)))You should see a (3, 2) array: first column 1,2,3, second column 4,5,6.
If inputs are already column-shaped (n, 1), column_stack behaves like a horizontal join of those columns (same outcome as hstack for that shape).
numpy.stack(..., axis=1)
numpy.stack joins arrays along a new axis. With axis=1, two 1-D arrays of length n become shape (n, 2)—another clear option when you want an explicit “new axis” story.
import numpy as np
p = np.array([1.0, 2.0, 3.0])
q = np.array([4.0, 5.0, 6.0])
print(np.stack((p, q), axis=1))You should see the same numeric layout as column_stack for this case.
numpy.hstack (when inputs are already column-shaped)
numpy.hstack stacks horizontally (along the last axis). For 2-D arrays with the same number of rows, that is column-wise joining—for example two (n, 1) blocks become (n, 2).
Important: for two 1-D arrays, hstack does not build two columns; it concatenates them into one longer 1-D array (length 2n). Use column_stack or stack(..., axis=1) when both inputs are 1-D.
import numpy as np
u = np.array([[1], [2], [3]])
v = np.array([[4], [5], [6]])
print(np.hstack((u, v)))You should see a (3, 2) array. Compare with 1-D hstack in the next snippet ({run=false}) so the difference is obvious.
import numpy as np
s = np.array([1, 2, 3])
t = np.array([4, 5, 6])
print(np.hstack((s, t)))[1 2 3 4 5 6]numpy.concatenate(..., axis=1)
numpy.concatenate is the general-purpose joiner. axis=1 means “glue columns”: every array must have the same number of rows, and sizes along other axes must match the rules in the error messages below.
import numpy as np
left = np.array([[1, 2], [3, 4]])
right = np.array([[5, 6, 7], [8, 9, 10]])
print(np.concatenate((left, right), axis=1))You should see a (2, 5) array (two rows, five columns).
Row-wise vs column-wise stacking
| Goal | Prefer |
|---|---|
| Two 1-D arrays as two columns of one matrix | np.column_stack or np.stack(..., axis=1) |
| Two 1-D arrays as one long 1-D sequence | np.hstack (or np.concatenate on 1-D with axis=0) |
| Stack rows (one array above the other) | np.vstack, np.row_stack, or np.stack(..., axis=0) |
| Add columns to existing 2-D arrays (same row count) | np.hstack or np.concatenate(..., axis=1) |
| Add rows to existing 2-D arrays (same column count) | np.vstack or np.concatenate(..., axis=0) |
| Named columns and mixed types | pandas DataFrame (see linked guide at the top of this page) |
Common mistakes and error messages
Different lengths
column_stack and stack require matching lengths along the shared dimension.
import numpy as np
np.column_stack((np.array([1, 2, 3]), np.array([4, 5])))ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 0, the array at index 0 has size 3 and the array at index 1 has size 2Wrong axis on 1-D
concatenate(..., axis=1) needs at least two dimensions.
import numpy as np
np.concatenate((np.array([1, 2, 3]), np.array([4, 5, 6])), axis=1)AxisError: axis 1 is out of bounds for array of dimension 12-D shape mismatch on concatenate(..., axis=1)
Row counts (or other axes) must align.
import numpy as np
a = np.ones((2, 3))
b = np.ones((3, 3))
np.concatenate((a, b), axis=1)ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 0, the array at index 0 has size 2 and the array at index 1 has size 3Expecting two columns from 1-D hstack
See the hstack one-line output above; use column_stack instead.
Choose the right tool
| Situation | Use |
|---|---|
Two 1-D arrays or lists → (n, 2) |
np.column_stack (or np.stack(..., axis=1)) |
| Want an explicit new axis API | np.stack(..., axis=1) |
Inputs already (n, 1) column blocks |
np.hstack or np.concatenate(..., axis=1) |
| General join of compatible 2-D blocks | np.concatenate (pick axis=0 or 1) |
| Tables with column names, heterogeneous columns | pandas DataFrame |
Summary
Search intent for “two column matrix” in Python usually means two NumPy columns from two 1-D sources—shape (n, 2). numpy.column_stack is the simplest match for that job; numpy.stack(..., axis=1) is an equally clear alternative. numpy.hstack fits when data is already column-shaped (n, 1); with plain 1-D inputs, hstack lengthens one axis instead of forming two columns. numpy.concatenate(..., axis=1) is the general 2-D column join, with stricter shape rules. Match row-wise stacking (vstack, axis=0) to column-wise stacking (column_stack, axis=1), watch length and axis mistakes, and use pandas when the goal is a real table, not just a numeric block.
References
- NumPy:
column_stack - NumPy:
stack - NumPy:
hstack - NumPy:
concatenate - NumPy: linear algebra routines (
numpy.linalg)

