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)
Frequently Asked Questions
How do I combine two arrays as two columns in NumPy?
Use numpy.column_stack when you have two equal-length 1-D arrays or lists: it returns shape (n, 2). For arrays that are already shaped as columns with shape (n, 1), numpy.hstack or numpy.concatenate(..., axis=1) also work if row counts match.
What is the difference between numpy column_stack and hstack?
column_stack treats each 1-D input as a column of a 2-D result. numpy.hstack joins arrays along the last axis; for two 1-D arrays it concatenates them into one longer 1-D array, not a two-column matrix—use column_stack or stack(..., axis=1) for two columns from 1-D data.
When should I use numpy concatenate with axis 1?
Use numpy.concatenate(..., axis=1) when you already have compatible 2-D arrays (same number of rows) and want a general column-wise join; all dimensions except the concatenation axis must match, unlike the friendlier 1-D case handled by column_stack.
Can I combine two Python lists into a matrix without NumPy?
You can build nested lists by hand, but NumPy (or pandas for labeled tables) is the usual choice for numeric matrices. NumPy functions accept sequences and return ndarray objects.
How do I stack two arrays as rows instead of columns?
Use numpy.vstack, numpy.row_stack, or numpy.stack(..., axis=0) when you want to stack vertically so the second array forms new rows below the first, not new columns beside it.

