Skip to main content

Python NumPy: How to Fix VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences

When creating NumPy arrays from Python lists or tuples, you might encounter the VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray. This warning signals that you are trying to create a NumPy array from a "ragged" sequence—a list or tuple where the inner elements (sub-lists or sub-tuples) have different lengths. While NumPy used to create an array of dtype=object implicitly in such cases, this behavior is now deprecated because it can lead to unexpected array structures and performance implications.

This guide will clearly explain what ragged nested sequences are, why creating NumPy arrays from them directly is deprecated, and provide the recommended solutions: explicitly specifying dtype=object if an array of Python objects is intended, or addressing the raggedness of your data if a true multi-dimensional numerical array was expected. We'll also cover how to manage or suppress this specific warning if absolutely necessary.

Understanding the Warning: Ragged Nested Sequences and dtype=object

What is a Ragged Nested Sequence?

A ragged nested sequence is a list (or tuple) of lists (or tuples, or ndarrays) where the inner sequences do not all have the same length or shape.

# Example of a ragged list of lists
ragged_list = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
# Inner lists have lengths 3, 2, and 4 respectively.

When visualized, such a structure would have "jagged" edges if you tried to represent it as a regular 2D grid.

Why is Direct Creation from Ragged Sequences Deprecated?

NumPy ndarrays are fundamentally designed to be homogeneous (all elements of the same C-type) and N-dimensional grids where each dimension has a consistent length. When you provide a ragged sequence to np.array() without specifying dtype=object:

  • NumPy can not create a standard multi-dimensional array with a consistent numerical dtype (like int64 or float64) because the "rows" have different numbers of "columns."
  • In older versions, NumPy would often default to creating a 1D array where each element is a Python object (in this case, each element would be one of the inner Python lists).
  • This implicit creation of an object array from ragged sequences is now deprecated because:
    • It can be inefficient due to storing Python objects rather than raw numbers.
    • It might hide data structure issues from the user.
    • It can lead to arrays that don't behave as expected with standard NumPy vectorized operations. The warning encourages you to be explicit if you truly intend to create an array of Python objects.

Reproducing the Warning

import numpy as np
import warnings # To demonstrate catching the warning for verification

ragged_input_list = [
[10, 20], # Length 2
[30, 40, 50], # Length 3
[60] # Length 1
]

print("Ragged input list:")
print(ragged_input_list)

# Attempt to create a NumPy array without specifying dtype=object
# This will trigger the VisibleDeprecationWarning
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always", np.VisibleDeprecationWarning) # Ensure we see it

# ⛔️ VisibleDeprecationWarning will be issued here
array_from_ragged_implicit = np.array(ragged_input_list)

print("Array created implicitly (triggers warning):")
print(array_from_ragged_implicit)
print(f"dtype: {array_from_ragged_implicit.dtype}") # Will be object
print(f"shape: {array_from_ragged_implicit.shape}") # Will be (3,) a 1D array of lists

if w:
print(f"Warning captured: {w[0].message}")
# Expected Warning Message:
# Creating an ndarray from ragged nested sequences ... is deprecated. If you meant to do this, you must specify 'dtype=object' ...
warning
  • Before NumPy 1.24: You’d get a VisibleDeprecationWarning for ragged lists.
  • As of NumPy 1.24+: You now get a ValueError, unless you explicitly use dtype=object.

Solution 1: Explicitly Specify dtype=object (If an Array of Objects is Intended)

If your goal is indeed to create a NumPy array where each element is a Python object (in this case, the inner lists themselves), the warning tells you exactly what to do: specify dtype=object.

Using np.array(..., dtype=object)

import numpy as np
ragged_input_list = [[10, 20], [30, 40, 50], [60]]

# ✅ Explicitly specify dtype=object
array_dtype_object = np.array(ragged_input_list, dtype=object)

print("Array created with dtype=object (no warning):")
print(array_dtype_object)
print(f"dtype: {array_dtype_object.dtype}")
# Output: object
print(f"shape: {array_dtype_object.shape}")
# Output: (3,)

# Each element of array_dtype_object is one of the inner Python lists.
print(f"First element: {array_dtype_object[0]}, type: {type(array_dtype_object[0])}")
# Output: First element: [10, 20], type: <class 'list'>

Output:

Array created with dtype=object (no warning):
[list([10, 20]) list([30, 40, 50]) list([60])]
dtype: object
shape: (3,)
First element: [10, 20], type: <class 'list'>
note

By specifying dtype=object, you are explicitly telling NumPy that you understand and intend to create an array of Python objects, thus silencing the deprecation warning.

Using np.asarray(..., dtype=object)

numpy.asarray() works similarly to np.array() but avoids making a copy if the input is already an ndarray of the correct type. When converting a list, its behavior regarding dtype=object for ragged sequences is similar.

import numpy as np

ragged_input_list = [[10, 20], [30, 40, 50], [60]]

# ✅ Using asarray with dtype=object
array_asarray_object = np.asarray(ragged_input_list, dtype=object)

print("Array created with np.asarray(dtype=object):")
print(array_asarray_object)
print(f"dtype: {array_asarray_object.dtype}") # Output: object

Output:

Array created with np.asarray(dtype=object):
[list([10, 20]) list([30, 40, 50]) list([60])]
dtype: object

Solution 2: Address the Raggedness of the Input Data (If a Homogeneous Numerical Array is Intended)

If you actually intended to create a 2D numerical NumPy array but your input list was ragged, simply specifying dtype=object might not be your true goal. Instead, you should pre-process your input list to make it non-ragged (i.e., all inner lists have the same length). This usually involves:

  • Padding: Adding placeholder values (e.g., np.nan, 0, or another sentinel value) to shorter inner lists to make them all the same length as the longest inner list.
  • Truncating: Shortening longer inner lists.
  • Re-evaluating Data Structure: Deciding if separate 1D arrays or a different data structure is more appropriate if the elements can not be made to fit a rectangular grid.

This approach is about fixing the data to fit NumPy's homogeneous N-D array model, rather than creating an array of objects. This is beyond the scope of just silencing the warning but is often the correct data processing step.

Managing the VisibleDeprecationWarning

While specifying dtype=object is the recommended way to handle intended ragged arrays, you can also control how Python/NumPy treats warnings.

Suppressing Only This Specific Warning

You can use the warnings module (or np.warnings) to filter out only np.VisibleDeprecationWarning.

import numpy as np
import warnings

ragged_input_list = [[10, 20], [30, 40, 50], [60]]

# Store old warning filters if you want to restore them
with warnings.catch_warnings():
# ✅ Ignore only VisibleDeprecationWarning from NumPy for this block
warnings.filterwarnings('ignore', category=np.VisibleDeprecationWarning)

array_warning_ignored = np.array(ragged_input_list) # No warning printed
print("Array created with VisibleDeprecationWarning ignored:")
print(array_warning_ignored)
print(f"dtype: {array_warning_ignored.dtype}") # Still object

# Warnings outside the 'with' block would behave as default.
# To set globally (use with caution):
# np.warnings.filterwarnings('ignore', category=np.VisibleDeprecationWarning)
warning
  • Before NumPy 1.24: You’d get a VisibleDeprecationWarning for ragged lists.
  • As of NumPy 1.24+: You now get a ValueError, unless you explicitly use dtype=object.

Temporarily Treating This Warning as an Error for Debugging

If you want to find all places in your code that trigger this warning and force them to be addressed, you can temporarily turn these warnings into errors.

import numpy as np
import warnings

ragged_input_list = [[10, 20], [30, 40, 50], [60]]

# Store old warning filters
with warnings.catch_warnings():
# ✅ Treat VisibleDeprecationWarning as an error for this block
warnings.filterwarnings('error', category=np.VisibleDeprecationWarning)

try:
print("Attempting array creation with warning set to error:")
# This line will now raise an np.VisibleDeprecationWarning exception
array_triggers_error = np.array(ragged_input_list)
print(array_triggers_error)
except np.VisibleDeprecationWarning as e:
print(f"Caught as error: {e}")
warning
  • Before NumPy 1.24: You’d get a VisibleDeprecationWarning for ragged lists.
  • As of NumPy 1.24+: You now get a ValueError, unless you explicitly use dtype=object.

This helps ensure you don't miss any instances where dtype=object should be explicitly stated or where data raggedness needs to be handled.

Conclusion

The VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences... is NumPy's way of guiding you towards more explicit and often more efficient array creation.

  1. If you intend to create a NumPy array where each element is a Python object (like the inner lists of a ragged sequence), the correct and future-proof solution is to explicitly specify dtype=object when calling np.array() or np.asarray(): arr = np.array(your_ragged_list, dtype=object)
  2. If you intended to create a homogeneous multi-dimensional numerical array but your input data was ragged, you need to pre-process your input list to ensure all sub-sequences have consistent lengths (e.g., by padding or truncating) before creating the NumPy array with a numerical dtype.
  3. Suppressing the warning should be a deliberate choice, used only after understanding its implications and preferably after confirming that dtype=object is indeed your intention.

By explicitly stating dtype=object for ragged inputs, you make your code clearer and align with modern NumPy practices.