How to get the diagonal elements of a matrix in Python

Learn how to get the diagonal elements of a matrix in Python. Explore various methods, tips, real-world uses, and common error fixes.

How to get the diagonal elements of a matrix in Python
Published on: 
Mon
Apr 6, 2026
Updated on: 
Wed
Apr 8, 2026
The Replit Team

You often need to get a matrix's diagonal elements in Python, a key task in data analysis and scientific computing. These elements run from the top-left to the bottom-right corner.

Here, you'll learn several techniques, like using NumPy's diagonal() function. The article covers practical tips, real-world applications, and debugging advice to help you master this essential skill.

Using numpy.diagonal() for a simple extraction

import numpy as np

matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
diagonal = matrix.diagonal()
print(diagonal)--OUTPUT--[1 5 9]

NumPy provides the diagonal() method as a highly efficient way to extract the main diagonal. Once your data is a NumPy array, you can call this method directly on it. This approach simplifies what would otherwise require manual looping through rows and columns.

The method returns a new one-dimensional array containing the diagonal elements. For the example matrix, it correctly pulls out the values [1 5 9], which correspond to the elements at indices (0,0), (1,1), and (2,2).

Basic matrix diagonal techniques

While NumPy is efficient, you can also extract a matrix diagonal using core Python methods like loops, list comprehensions, or by creating a dedicated function.

Using a for loop with nested lists

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
diagonal = []
for i in range(min(len(matrix), len(matrix[0]))):
diagonal.append(matrix[i][i])
print(diagonal)--OUTPUT--[1, 5, 9]

A for loop offers a fundamental way to handle nested lists. This method iterates through the matrix's indices, using min(len(matrix), len(matrix[0])) to safely handle rectangular matrices without causing errors.

  • The core of this technique is accessing elements with matching row and column indices using matrix[i][i].
  • Each element found on the diagonal is then appended to a new list, building your result step-by-step.

Using list comprehension for a cleaner approach

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
diagonal = [matrix[i][i] for i in range(min(len(matrix), len(matrix[0])))]
print(diagonal)--OUTPUT--[1, 5, 9]

List comprehensions offer a more concise and often more readable alternative to traditional for loops. You can think of it as packing the loop and the element selection into a single, elegant line of code.

  • The expression matrix[i][i] specifies what to add to the new list.
  • The for i in range(...) part iterates through the indices, just like in the loop version.

This approach creates the final list directly, making your code more streamlined and "Pythonic."

Creating a diagonal-specific function

def get_diagonal(matrix):
return [matrix[i][i] for i in range(min(len(matrix), len(matrix[0])))]

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(get_diagonal(matrix))--OUTPUT--[1, 5, 9]

Encapsulating the logic in a dedicated function like get_diagonal is a smart move for reusability. It takes the list comprehension from the previous example and makes it callable for any matrix you pass to it. This keeps your main code cleaner and more focused on the bigger picture.

  • Your code becomes more readable since get_diagonal(matrix) clearly states its intent.
  • It's also easier to maintain. If you ever need to adjust the logic, you only have to change it inside this one function.

Advanced diagonal extraction

Beyond the basic methods, NumPy's numpy.diag() function offers greater flexibility for extracting any diagonal from both square and non-square matrices.

Using numpy.diag() for more control

import numpy as np

matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
diagonal = np.diag(matrix)
print(diagonal)--OUTPUT--[1 5 9]

Unlike the diagonal() method, numpy.diag() is a standalone function that takes the array as an argument. By default, it extracts the main diagonal, just like the method. However, its key advantage is an optional k parameter that gives you more control.

  • This parameter lets you extract off-diagonals. For instance, k=1 gets the diagonal above the main one, and k=-1 gets the one below.

Extracting off-diagonal elements with k parameter

import numpy as np

matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
upper_diagonal = np.diag(matrix, k=1) # Elements above main diagonal
lower_diagonal = np.diag(matrix, k=-1) # Elements below main diagonal
print(f"Upper diagonal: {upper_diagonal}\nLower diagonal: {lower_diagonal}")--OUTPUT--Upper diagonal: [2 6]
Lower diagonal: [4 8]

The k parameter tells NumPy how many steps to shift from the main diagonal. A positive value shifts the target diagonal up and to the right, while a negative value shifts it down and to the left.

  • Setting k=1 targets the first upper diagonal. In the example, this extracts the elements [2 6].
  • Using k=-1 grabs the first lower diagonal, which correctly returns the elements [4 8].

This simple offset makes it easy to analyze specific bands of data within a matrix without complex indexing.

Working with non-square matrices

import numpy as np

non_square = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
diagonal = np.diag(non_square)
print(f"Matrix shape: {non_square.shape}\nDiagonal: {diagonal}")--OUTPUT--Matrix shape: (3, 4)
Diagonal: [1 6 11]

The numpy.diag() function isn't limited to square matrices; it handles rectangular shapes without any extra work. It continues to extract elements where the row and column indices are identical, just as it does with square arrays.

  • For the 3x4 matrix example, it correctly identifies [1 6 11] as the diagonal.
  • The process stops when it can no longer find a matching index pair. This happens when it reaches the end of the shortest dimension, which in this case is the three rows.

Move faster with Replit

Replit is an AI-powered development platform where all Python dependencies come pre-installed, so you can skip setup and start coding instantly. This lets you move from learning individual techniques to building complete applications with Agent 4. Just describe your idea, and it will handle the code, databases, APIs, and deployment.

Instead of piecing together techniques, you can describe the app you want to build and let Agent 4 take it from idea to working product:

  • A linear algebra calculator that computes a matrix's trace by extracting its main diagonal.
  • An image analysis utility that pulls diagonal pixel data to check for specific visual patterns.
  • A game logic module that validates winning moves along the diagonals of a game board.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

Extracting diagonals is usually straightforward, but a few common pitfalls can trip you up when working with different data structures and library versions.

Dealing with read-only diagonals in older numpy versions

In older versions of NumPy, calling the .diagonal() method on an array returned a read-only "view" of the diagonal, not a new, modifiable array. This meant you couldn't change the values of the extracted diagonal directly, which could be a frustrating surprise.

  • If you tried to assign a new value to an element in the view, you'd get an error.
  • The modern solution is to explicitly create a mutable copy by appending .copy() to your extraction call, like matrix.diagonal().copy().

Handling IndexError with irregular nested lists

When you're not using NumPy, a common issue is the IndexError. This happens if you try to get a diagonal from a "jagged" list of lists—where the inner lists have different lengths. A standard loop or list comprehension using matrix[i][i] will fail if it tries to access an index that doesn't exist in a shorter row.

  • This error occurs because the assumption of a uniform, rectangular structure doesn't hold.
  • You can prevent this by ensuring your loop's range is limited by the shortest dimension, as shown in the earlier examples with min().

Forgetting to convert lists to numpy arrays with np.diag()

The np.diag() function is powerful, but it expects a NumPy array as its input. If you pass it a standard Python list of lists, it won't extract the diagonal as you might expect. The function's behavior changes based on the input's dimensions, and it doesn't automatically convert lists for you.

  • To get the correct behavior, you must first convert your list into a NumPy array using np.array().
  • Without this conversion, you'll get unexpected results instead of the diagonal elements you were looking for.

Dealing with read-only diagonals in older numpy versions

With older NumPy versions, attempting to modify a diagonal extracted with the diagonal() method could be a frustrating dead end. The method returned a read-only view, preventing direct changes. See how this plays out in the code example below.

import numpy as np

matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
diagonal = matrix.diagonal()
diagonal[0] = 99 # Attempt to modify diagonal
print(matrix) # Changes might not be reflected in original matrix

Attempting to change the first element with diagonal[0] = 99 will raise an error. This happens because the diagonal() method returns a non-writable view, not a new array. Check out the corrected approach below.

import numpy as np

matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
np.fill_diagonal(matrix, [99, 55, 33]) # Reliable way to modify diagonal
print(matrix)

To reliably change a diagonal, use NumPy’s np.fill_diagonal() function. It modifies the original matrix directly, sidestepping the read-only view problem you might encounter in older versions.

  • This function takes the matrix and an array of new values as arguments.
  • It's the recommended approach for in-place diagonal updates, ensuring your changes stick without needing to create a separate copy of the data.

Handling IndexError with irregular nested lists

When your nested lists aren't uniform, you'll hit an IndexError. This happens because a simple list comprehension tries to access an index that doesn't exist in a shorter row. See how this plays out in the following code example.

irregular_matrix = [[1, 2, 3], [4, 5], [7, 8, 9]]
diagonal = [irregular_matrix[i][i] for i in range(len(irregular_matrix))]
print(diagonal)

The IndexError occurs because range(len(irregular_matrix)) iterates up to the total number of rows. It fails when trying to access irregular_matrix[i][i] on a row that is shorter than its index i. The code below demonstrates the fix.

irregular_matrix = [[1, 2, 3], [4, 5], [7, 8, 9]]
diagonal = []
for i in range(len(irregular_matrix)):
if i < len(irregular_matrix[i]):
diagonal.append(irregular_matrix[i][i])
print(diagonal)

The solution adds a simple but crucial check inside the loop. Before accessing an element, it confirms the row is long enough to prevent an error.

  • The condition if i < len(irregular_matrix[i]) stops the IndexError by making sure you don't look for an index that doesn't exist.

This is a key safeguard when your data isn't perfectly uniform, which often happens with data from files or external APIs.

Forgetting to convert lists to numpy arrays with np.diag()

It's easy to forget that np.diag() expects a NumPy array, not a plain Python list. If you pass it a list, the function behaves differently and won't extract the diagonal you want. The code below shows what happens.

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
diagonal = np.diag(matrix) # Will raise TypeError
print(diagonal)

The np.diag() function treats the 2D list as elements for a new diagonal matrix, not as a source to extract from. This causes a TypeError. The code below demonstrates the correct implementation.

import numpy as np

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
diagonal = np.diag(np.array(matrix))
print(diagonal)

The solution is to wrap your list in np.array() before passing it to np.diag(). This simple step ensures NumPy treats your data as a matrix to extract from, rather than misinterpreting it.

  • This conversion is crucial when your data comes from sources like files or APIs as standard Python lists.
  • Without it, np.diag() will not behave as expected for diagonal extraction.

Real-world applications

Extracting diagonals is more than a technical exercise—it's a key operation in data science for validating matrices and analyzing feature variances.

Using np.diag() to validate correlation matrices

Since a variable's correlation with itself is always 1.0, you can use np.diag() to quickly extract the diagonal of a correlation matrix and verify its integrity.

import numpy as np

corr_matrix = np.array([[1.0, 0.8, 0.3],
[0.8, 1.0, 0.5],
[0.3, 0.5, 1.0]])

diag_elements = np.diag(corr_matrix)
is_valid = np.all(diag_elements == 1.0)
print(diag_elements)
print(f"Valid correlation matrix: {is_valid}")

This code performs a quick validation check on a matrix. It uses np.diag() to extract the main diagonal, which in this case is [1.0, 1.0, 1.0]. The real work happens in the next step, where it confirms every one of those values is 1.0.

  • The comparison diag_elements == 1.0 produces a boolean array ([True, True, True]).
  • The np.all() function then checks if every value in that array is True.

Since they are, the final output confirms the matrix passes this specific test by printing True.

Analyzing feature variances with np.diag()

You can also use np.diag() to pull the variance of each feature directly from a covariance matrix, as these values always lie on the main diagonal.

import numpy as np

features = np.array([
[2.5, 0.5, 2.2],
[0.1, 1.3, 1.3],
[2.1, 0.7, 3.1],
[1.5, 0.2, 2.8],
[3.1, 0.8, 1.5]
])

cov_matrix = np.cov(features, rowvar=False)
print(cov_matrix)

variances = np.diag(cov_matrix)
for i, var in enumerate(variances):
print(f"Feature {i+1} variance: {var:.2f}")

This code calculates how much each feature varies using NumPy. It starts by feeding the feature data into np.cov(), with rowvar=False specified so that each column is treated as a distinct feature. This generates a covariance matrix.

  • The np.diag() function then pulls out the main diagonal from this matrix.
  • A loop iterates through these diagonal values, printing the variance for each feature. This shows how spread out each feature's data is from its average.

Get started with Replit

Now, turn this knowledge into a real tool. Tell Replit Agent: "Build a web app that calculates a matrix's trace" or "Create a Python utility to validate correlation matrices from a CSV."

It writes the code, tests for errors, and deploys your application. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.