NumPy - Append Elements to Array (np.append)
• `np.append()` creates a new array rather than modifying in place, making it inefficient for repeated operations in loops—use lists or pre-allocation instead
Key Insights
• np.append() creates a new array rather than modifying in place, making it inefficient for repeated operations in loops—use lists or pre-allocation instead
• The axis parameter determines whether elements are appended to a flattened array (axis=None) or along a specific dimension, requiring shape compatibility
• For building arrays incrementally, np.concatenate(), np.vstack(), or np.hstack() often provide better performance and clearer intent than repeated np.append() calls
Basic Syntax and Single Element Append
The np.append() function adds elements to the end of a NumPy array. The basic syntax is numpy.append(arr, values, axis=None). When axis is None, the function flattens both the array and values before appending.
import numpy as np
# Append single element to 1D array
arr = np.array([1, 2, 3, 4])
result = np.append(arr, 5)
print(result) # [1 2 3 4 5]
# Append multiple elements
arr = np.array([1, 2, 3])
result = np.append(arr, [4, 5, 6])
print(result) # [1 2 3 4 5 6]
# Original array remains unchanged
print(arr) # [1 2 3]
Since np.append() returns a new array, you must assign the result to a variable. The original array remains unmodified because NumPy arrays are immutable in size.
Appending to Multidimensional Arrays
When working with multidimensional arrays, the axis parameter controls the append direction. Without specifying axis, the function flattens the array.
# 2D array without axis specification (flattens)
arr_2d = np.array([[1, 2], [3, 4]])
result = np.append(arr_2d, [[5, 6]])
print(result) # [1 2 3 4 5 6]
# Append along axis 0 (rows)
arr_2d = np.array([[1, 2], [3, 4]])
new_row = np.array([[5, 6]])
result = np.append(arr_2d, new_row, axis=0)
print(result)
# [[1 2]
# [3 4]
# [5 6]]
# Append along axis 1 (columns)
arr_2d = np.array([[1, 2], [3, 4]])
new_col = np.array([[5], [6]])
result = np.append(arr_2d, new_col, axis=1)
print(result)
# [[1 2 5]
# [3 4 6]]
The dimensions must be compatible along the non-append axis. Attempting to append incompatible shapes raises a ValueError.
# This will raise ValueError
arr_2d = np.array([[1, 2], [3, 4]])
incompatible = np.array([[5, 6, 7]]) # 3 columns vs 2
# result = np.append(arr_2d, incompatible, axis=0) # ValueError
Performance Considerations and Alternatives
The critical issue with np.append() is performance. Each call creates a new array and copies all existing data, resulting in O(n²) complexity when used in loops.
import time
# Bad: Using np.append in a loop
start = time.time()
arr = np.array([])
for i in range(10000):
arr = np.append(arr, i)
bad_time = time.time() - start
# Good: Pre-allocate array
start = time.time()
arr = np.empty(10000)
for i in range(10000):
arr[i] = i
good_time = time.time() - start
# Best: Use native Python list then convert
start = time.time()
lst = []
for i in range(10000):
lst.append(i)
arr = np.array(lst)
best_time = time.time() - start
print(f"np.append in loop: {bad_time:.4f}s")
print(f"Pre-allocation: {good_time:.4f}s")
print(f"List then convert: {best_time:.4f}s")
For building arrays incrementally, use these alternatives:
# Alternative 1: np.concatenate for multiple arrays
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr3 = np.array([7, 8, 9])
result = np.concatenate([arr1, arr2, arr3])
print(result) # [1 2 3 4 5 6 7 8 9]
# Alternative 2: np.vstack for vertical stacking
row1 = np.array([1, 2, 3])
row2 = np.array([4, 5, 6])
result = np.vstack([row1, row2])
print(result)
# [[1 2 3]
# [4 5 6]]
# Alternative 3: np.hstack for horizontal stacking
col1 = np.array([[1], [2], [3]])
col2 = np.array([[4], [5], [6]])
result = np.hstack([col1, col2])
print(result)
# [[1 4]
# [2 5]
# [3 6]]
Working with 3D Arrays and Higher Dimensions
For higher-dimensional arrays, understanding axis becomes crucial. Each axis represents a different dimension of the array structure.
# 3D array: (2, 3, 4) - 2 blocks, 3 rows, 4 columns
arr_3d = np.array([
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]],
[[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]]
])
# Append along axis 0 (add new block)
new_block = np.array([[[25, 26, 27, 28], [29, 30, 31, 32], [33, 34, 35, 36]]])
result = np.append(arr_3d, new_block, axis=0)
print(result.shape) # (3, 3, 4)
# Append along axis 1 (add new row to each block)
new_rows = np.array([[[37, 38, 39, 40]], [[41, 42, 43, 44]]])
result = np.append(arr_3d, new_rows, axis=1)
print(result.shape) # (2, 4, 4)
# Append along axis 2 (add new column to each row)
new_cols = np.array([
[[45], [46], [47]],
[[48], [49], [50]]
])
result = np.append(arr_3d, new_cols, axis=2)
print(result.shape) # (2, 3, 5)
Practical Use Cases
Despite performance limitations, np.append() works well for small, one-time operations where code clarity matters more than speed.
# Adding padding to an array
def add_padding(arr, pad_value=0, pad_size=1):
padding = np.full(pad_size, pad_value)
return np.append(padding, np.append(arr, padding))
data = np.array([10, 20, 30])
padded = add_padding(data, pad_value=0, pad_size=2)
print(padded) # [ 0 0 10 20 30 0 0]
# Combining measurement data from multiple sensors
sensor1_data = np.array([23.5, 24.1, 23.8])
sensor2_data = np.array([24.0, 23.9, 24.2])
combined = np.append(sensor1_data, sensor2_data)
print(f"All measurements: {combined}")
print(f"Average: {combined.mean():.2f}")
# Building a feature vector incrementally
def create_feature_vector(raw_data):
features = np.array([])
features = np.append(features, raw_data.mean())
features = np.append(features, raw_data.std())
features = np.append(features, raw_data.max())
features = np.append(features, raw_data.min())
return features
measurements = np.array([15, 18, 22, 19, 21, 17])
feature_vec = create_feature_vector(measurements)
print(feature_vec) # [18.67 2.42 22. 15. ]
Common Pitfalls and Solutions
Understanding these common mistakes prevents bugs and performance issues.
# Pitfall 1: Forgetting to assign the result
arr = np.array([1, 2, 3])
np.append(arr, 4) # Does nothing
print(arr) # [1 2 3] - unchanged
# Solution: Always assign the result
arr = np.append(arr, 4)
print(arr) # [1 2 3 4]
# Pitfall 2: Shape mismatch with axis parameter
arr = np.array([[1, 2], [3, 4]])
# np.append(arr, [5, 6], axis=0) # ValueError: all inputs must have same number of dimensions
# Solution: Ensure compatible shapes
arr = np.append(arr, [[5, 6]], axis=0) # Correct
print(arr)
# Pitfall 3: Using append when concatenate is clearer
arrays = [np.array([1, 2]), np.array([3, 4]), np.array([5, 6])]
# Using append (confusing)
result = arrays[0]
for a in arrays[1:]:
result = np.append(result, a)
# Using concatenate (clear intent)
result = np.concatenate(arrays)
print(result) # [1 2 3 4 5 6]
Use np.append() for simple, one-time operations on small arrays. For performance-critical code or repeated operations, pre-allocate arrays or use Python lists with final conversion. For combining multiple arrays, prefer np.concatenate(), np.vstack(), or np.hstack() for better readability and performance.