If you’ve ever needed to flip rows and columns in your data, converting a 3×4 matrix into a 4×3 one, that’s exactly what transposing an array in Python. In this tutorial, I’ll walk you through five different ways to do it: using NumPy’s transpose() function, the .T shortcut, Python’s built-in zip(), list comprehension, and nested loops.
I’ll also cover a gotcha that trips up a lot of people: why transposing a 1D NumPy array does nothing. That one has caught me off guard more than once.
Whether you’re working on a data analysis task, building a machine learning pipeline, or just want to understand how matrix operations work in Python, this guide has you covered.
What Does It Mean to Transpose an Array in Python?
Transposing an array means flipping it over its diagonal — rows become columns and columns become rows. The element at position (i, j) in the original array moves to position (j, i) in the transposed one.
Here’s the simplest way to see it:
Original (3 rows × 3 cols): Transposed (3 cols × 3 rows):
[1, 2, 3] [1, 4, 7]
[4, 5, 6] ──────► [2, 5, 8]
[7, 8, 9] [3, 6, 9]
Notice that the first column [1, 4, 7] of the original becomes the first row of the transposed result. That’s the core idea.
This comes up constantly in real Python work: rotating data from “one row per transaction” into “one row per category,” preparing input arrays for scikit-learn or TensorFlow, or reshaping data before visualizing it with Matplotlib.
Method 1: Transpose a NumPy Array with np.transpose()
This is the go-to method when you’re working with NumPy arrays (which is most of the time in data work). The numpy.transpose() function is clean, readable, and handles arrays of any dimension.
Install NumPy first if you haven’t already:
pip install numpy
Example — Transposing a 2D NumPy array:
import numpy as np
# Quarterly revenue data: 3 products × 4 quarters
revenue = np.array([
[12000, 15000, 18000, 22000], # Product A
[9000, 11000, 13000, 16000], # Product B
[7500, 8200, 9100, 10500] # Product C
])
print("Original shape:", revenue.shape)
print(revenue)
transposed = np.transpose(revenue)
print("\nTransposed shape:", transposed.shape)
print(transposed)
Output:
Original shape: (3, 4)
[[12000 15000 18000 22000]
[ 9000 11000 13000 16000]
[ 7500 8200 9100 10500]]
Transposed shape: (4, 3)
[[12000 9000 7500]
[15000 11000 8200]
[18000 13000 9100]
[22000 16000 10500]]
I executed the above example code and added the screenshot below.

After transposing, each row now represents a quarter, and each column represents a product. That’s much easier to analyze if you’re looking at quarter-over-quarter trends.
Syntax:
numpy.transpose(a, axes=None)
a— the input arrayaxes— optional; lets you specify a custom axis order for 3D+ arrays. If you leave it asNone(the default), it reverses the axes, which for 2D arrays means swapping rows and columns.
Method 2: Transpose a NumPy Array with .T
The .T attribute is just a shortcut for np.transpose(). It does the same thing with less typing. I use this one all the time when I’m writing quick scripts or working in a Jupyter notebook.
import numpy as np
scores = np.array([
[88, 92, 79], # Student: Alex
[74, 85, 91], # Student: Jordan
[95, 88, 83] # Student: Casey
])
transposed_scores = scores.T
print("Original (students × subjects):")
print(scores)
print("\nTransposed (subjects × students):")
print(transposed_scores)
Output:
Original (students × subjects):
[[88 92 79]
[74 85 91]
[95 88 83]]
Transposed (subjects × students):
[[88 74 95]
[92 85 88]
[79 91 83]]
I executed the above example code and added the screenshot below.

Use .T when you want a quick, readable one-liner. Use np.transpose() when you need the axes parameter to reorder a 3D array.
Method 3: Transpose a List of Lists Using zip()
If you’re working with plain Python lists (no NumPy), zip() is the cleanest way to transpose? It’s fast, readable, and built right into Python — no imports needed.
# Monthly sales data: 3 sales reps × 4 months
sales = [
[4200, 5100, 4800, 5600], # Rep: Sarah
[3800, 4400, 4100, 4900], # Rep: Mike
[5100, 5500, 5200, 6000] # Rep: Lisa
]
transposed = [list(col) for col in zip(*sales)]
print("Original (reps × months):")
for row in sales:
print(row)
print("\nTransposed (months × reps):")
for row in transposed:
print(row)
Output:
Original (reps × months):
[4200, 5100, 4800, 5600]
[3800, 4400, 4100, 4900]
[5100, 5500, 5200, 6000]
Transposed (months × reps):
[4200, 3800, 5100]
[5100, 4400, 5500]
[4800, 4100, 5200]
[5600, 4900, 6000]
I executed the above example code and added the screenshot below.

How does zip(*sales) work?
The * unpacks the list of lists into separate arguments. zip() then groups the first element from each sublist, then the second, and so on — essentially reading the data column by column instead of row by row. The result from zip() is tuples, so you wrap each in list() to get a list of lists back.
One thing to watch out for: zip() silently stops at the shortest row if your rows have unequal lengths. If you have ragged data, use itertools.zip_longest() instead:
from itertools import zip_longest
ragged = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
transposed = [list(col) for col in zip_longest(*ragged, fillvalue=0)]
print(transposed)
# [[1, 4, 6], [2, 5, 7], [3, 0, 8], [0, 0, 9]]
Method 4: Transpose Using List Comprehension
If you want to understand exactly what’s happening under the hood, or you can’t use NumPy or zip(), list comprehension is a great option. It’s explicit and readable once you get the pattern.
# City temperature data: 3 cities × 5 days
temps = [
[72, 75, 68, 70, 74], # City: Denver
[85, 88, 82, 86, 89], # City: Austin
[61, 63, 59, 64, 62] # City: Seattle
]
rows = len(temps)
cols = len(temps[0])
transposed = [[temps[row][col] for row in range(rows)] for col in range(cols)]
print("Original (cities × days):")
for row in temps:
print(row)
print("\nTransposed (days × cities):")
for row in transposed:
print(row)
Output:
Original (cities × days):
[72, 75, 68, 70, 74]
[85, 88, 82, 86, 89]
[61, 63, 59, 64, 62]
Transposed (days × cities):
[72, 85, 61]
[75, 88, 63]
[68, 82, 59]
[70, 86, 64]
[74, 89, 62]
The outer loop iterates over column indices (col), and the inner loop picks that column’s value from each row. This gives you a new list where the columns of the original become the rows.
Just keep in mind: this assumes all rows have the same length. If they don’t, you’ll get an IndexError.
Method 5: Transpose Using Nested Loops
This is the most explicit approach. I wouldn’t use it in production code, but it’s really useful if you’re teaching someone the transpose concept or need fine-grained control over each element assignment.
# Store inventory: 3 stores × 4 product categories
inventory = [
[120, 85, 200, 65], # Store: Chicago
[95, 110, 175, 80], # Store: Houston
[140, 90, 215, 70] # Store: Phoenix
]
rows = len(inventory)
cols = len(inventory[0])
# Create an empty result array with flipped dimensions
transposed = [[0 for _ in range(rows)] for _ in range(cols)]
for i in range(rows):
for j in range(cols):
transposed[j][i] = inventory[i][j]
print("Original (stores × categories):")
for row in inventory:
print(row)
print("\nTransposed (categories × stores):")
for row in transposed:
print(row)
Output:
Original (stores × categories):
[120, 85, 200, 65]
[95, 110, 175, 80]
[140, 90, 215, 70]
Transposed (categories × stores):
[120, 95, 140]
[85, 110, 90]
[200, 175, 215]
[65, 80, 70]
The key step here is pre-creating the transposed list with the correct flipped dimensions (cols × rows). Then you simply place each inventory[i][j] into transposed[j][i].
The 1D Array Gotcha: Why .T Does Nothing
This one trips up a lot of people, including me, the first time I hit it. If you try to transpose a 1D NumPy array, nothing changes.
import numpy as np
scores = np.array([88, 74, 95, 62, 83])
print("Original:", scores)
print("After .T:", scores.T)
print("Shape:", scores.T.shape)
Output:
Original: [88 74 95 62 83]
After .T: [88 74 95 62 83]
Shape: (5,)
Same array. Same shape. Nothing changed.
Why? Transposing reverses the axes of an array. A 1D array only has one axis, so there’s nothing to reverse. It’s mathematically identical to itself.
What you probably wanted — a column vector:
If you want to turn a 1D array into a 2D column vector, you need to add a second dimension first explicitly:
import numpy as np
scores = np.array([88, 74, 95, 62, 83])
# Option 1: reshape
col_vector = scores.reshape(-1, 1)
print(col_vector)
print("Shape:", col_vector.shape)
# Option 2: np.newaxis
col_vector2 = scores[:, np.newaxis]
print(col_vector2)
Output:
[[88]
[74]
[95]
[62]
[83]]
Shape: (5, 1)
Now you have a proper 5×1 column vector that can be transposed into a 1×5 row vector.
This comes up often in machine learning workflows, whether you’re reshaping feature vectors before passing them to scikit-learn or performing matrix multiplication with NumPy.
Transposing a 3D Array: Axes Explained
For most everyday work, you’re transposing 2D arrays. But if you’re working with image data, video frames, or batched tensors in ML, you’ll run into 3D arrays.
import numpy as np
# Shape: (2 batches, 3 rows, 4 columns)
arr_3d = np.arange(24).reshape(2, 3, 4)
print("Original shape:", arr_3d.shape)
# Default transpose reverses all axes
default_t = np.transpose(arr_3d)
print("Default transpose shape:", default_t.shape)
# Shape: (4, 3, 2)
# Custom: swap only the last two axes (rows and columns within each batch)
custom_t = np.transpose(arr_3d, axes=(0, 2, 1))
print("Custom transpose shape:", custom_t.shape)
# Shape: (2, 4, 3)
The axes parameter tells NumPy how to rearrange the dimensions. (0, 2, 1) means “keep axis 0 in place, swap axes 1 and 2” — which is what you’d normally want when transposing matrices within a batch.
Common Mistakes When Transposing Arrays in Python
Here are the mistakes I see most often:
- Calling
.Ton a 1D array and expecting a column vector. It won’t change the shape. Add a dimension first with reshape(-1, 1) or [:, np.newaxis]. - Forgetting that
zip()returns tuples, not lists. Wrap with list() like this: [list(col) for col in zip(*arr)]. - Using
zip()on ragged arrays. It silently drops the extra elements from longer rows. Use itertools.zip_longest() if your rows have different lengths. - List comprehension on uneven rows. You’ll get an IndexError because len(arr[0]) only checks the first row’s length.
- Confusing reshape with transpose. reshape(4, 3) rearranges element order. transpose() swaps axes without touching element order. They’re different operations.
Which Method Should You Use?
| Method | Best for | Handles NumPy arrays? | Handles plain Python lists? |
|---|---|---|---|
np.transpose() | NumPy arrays, 3D+ with custom axes | ✅ Yes | ✅ Converts automatically |
.T shortcut | Quick 2D array flip | ✅ Yes | ❌ No |
zip(*arr) | Clean pure-Python list transpose | ❌ Not ideal | ✅ Yes |
| List comprehension | Learning or custom logic on lists | ❌ Not ideal | ✅ Yes |
| Nested loops | Teaching, full manual control | ❌ Not ideal | ✅ Yes |
My personal recommendation:
- If you’re using NumPy, use .T for 2D and np.transpose(arr, axes=(…)) for 3D.
- If you’re working with plain Python lists, use zip().
- If you’re explaining the concept to someone learning Python, use list comprehension or loops; they make the logic visible.
Real-World Use Case: Preparing Data for Machine Learning
Here’s a quick example of where transposing shows up in a real ML workflow. Say you’ve got a dataset where each row is a feature and each column is a sample, but scikit-learn expects rows to be samples and columns to be features.
import numpy as np
from sklearn.preprocessing import StandardScaler
# 4 features × 5 samples (wrong orientation for sklearn)
raw_data = np.array([
[170, 175, 162, 180, 168], # Feature: height (cm)
[68, 75, 55, 85, 62], # Feature: weight (kg)
[25, 30, 22, 35, 28], # Feature: age
[1, 0, 1, 0, 1] # Feature: category
])
print("Wrong shape for sklearn:", raw_data.shape)
# Transpose to get 5 samples × 4 features
X = raw_data.T
print("Correct shape for sklearn:", X.shape)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
print("Scaled data shape:", X_scaled.shape)
Output:
Wrong shape for sklearn: (4, 5)
Correct shape for sklearn: (5, 4)
Scaled data shape: (5, 4)
One line — raw_data.T, and the data goes from the wrong orientation to the right one for the entire sklearn pipeline.
Frequently Asked Questions
Can I transpose a 1D Python list?
Not in the traditional sense, because a 1D list has no rows or columns to swap. You’d first need to nest it inside another list to make it 2D.
Does np.transpose() copy the data?
No — it returns a view of the original array, not a copy. That means it’s fast and memory-efficient. If you modify the transposed array, you’ll also change the original. Use .copy() if you need an independent copy.
What’s the difference between numpy.transpose() and numpy.reshape()?
transpose() swaps axes — the data stays in the same memory locations but its dimensions are reinterpreted. reshape() changes the shape while potentially moving data in memory. They’re different operations and not interchangeable.
Does transposing work on pandas DataFrames too?
Yes! Pandas has the same .T attribute. df.T transposes a DataFrame, turning columns into rows and rows into columns.
Summary
Here’s a quick recap of everything covered:
- np.transpose(arr) — Most versatile. Works on any NumPy array, supports 3D+ with the
axesparameter. - arr.T — Fastest to type. Perfect for 2D NumPy arrays.
- zip(*arr) — Best for plain Python lists. Clean and dependency-free.
- List comprehension — Good for understanding the logic manually.
- Nested loops — Most explicit. Great for learning, but verbose.
- 1D NumPy arrays — Always reshape to 2D first before transposing if you need a column/row vector.
You may also read:
- Find the Index of the Maximum Value in an Array Using Python
- Reverse an Array in Python
- Read a File into an Array in Python
- Initialize an Array in Python

Bijay Kumar is an experienced Python and AI professional who enjoys helping developers learn modern technologies through practical tutorials and examples. His expertise includes Python development, Machine Learning, Artificial Intelligence, automation, and data analysis using libraries like Pandas, NumPy, TensorFlow, Matplotlib, SciPy, and Scikit-Learn. At PythonGuides.com, he shares in-depth guides designed for both beginners and experienced developers. More about us.