How to Create a Ones Array in NumPy

NumPy's ones array is one of those deceptively simple tools that shows up everywhere in numerical computing. You'll reach for it when initializing neural network biases, creating boolean masks for...

Key Insights

  • np.ones() creates arrays filled with ones and accepts shape, dtype, and order parameters—defaulting to float64 which may waste memory for simple counting or masking operations.
  • np.ones_like() is the pragmatic choice when you need a ones array matching an existing array’s shape and dtype, eliminating manual shape extraction and reducing bugs.
  • For performance-critical code, pre-allocating with np.ones() beats growing arrays dynamically, but np.empty() followed by fill() can be faster when you’ll overwrite most values anyway.

Introduction

NumPy’s ones array is one of those deceptively simple tools that shows up everywhere in numerical computing. You’ll reach for it when initializing neural network biases, creating boolean masks for filtering data, building placeholder arrays for image processing, or setting up matrices for linear algebra operations.

While np.ones() seems trivial—it just creates an array full of ones—understanding its parameters and variations will save you debugging time and memory headaches. This article covers everything from basic usage to performance optimization, with practical examples you can use immediately.

Basic Syntax: np.ones()

The function signature is straightforward:

numpy.ones(shape, dtype=float, order='C')

Three parameters control the output:

  • shape: An integer or tuple of integers defining array dimensions
  • dtype: The data type of array elements (defaults to float64)
  • order: Memory layout—'C' for row-major (C-style) or 'F' for column-major (Fortran-style)

Here’s how to create basic ones arrays:

import numpy as np

# 1D array with 5 elements
ones_1d = np.ones(5)
print(ones_1d)
# Output: [1. 1. 1. 1. 1.]

print(ones_1d.dtype)
# Output: float64

# 2D array with 3 rows and 4 columns
ones_2d = np.ones((3, 4))
print(ones_2d)
# Output:
# [[1. 1. 1. 1.]
#  [1. 1. 1. 1.]
#  [1. 1. 1. 1.]]

# Single integer for 1D, tuple for multi-dimensional
# This is a common source of errors for beginners
ones_matrix = np.ones((2, 2))  # Correct: 2x2 matrix
# ones_matrix = np.ones(2, 2)  # Wrong: raises TypeError

Notice the decimal points in the output. NumPy defaults to float64, which uses 8 bytes per element. For a million-element array, that’s 8 MB of memory—potentially wasteful if you only need integers.

Specifying Data Types

The dtype parameter controls memory usage and numeric precision. Choose deliberately:

import numpy as np

# Integer ones - useful for counting, indexing
ones_int32 = np.ones(5, dtype=np.int32)
print(ones_int32)
# Output: [1 1 1 1 1]
print(ones_int32.dtype)
# Output: int32

# Single precision float - half the memory of float64
ones_float32 = np.ones((1000, 1000), dtype=np.float32)
print(f"Memory usage: {ones_float32.nbytes / 1024 / 1024:.2f} MB")
# Output: Memory usage: 3.81 MB

# Compare with default float64
ones_float64 = np.ones((1000, 1000))
print(f"Memory usage: {ones_float64.nbytes / 1024 / 1024:.2f} MB")
# Output: Memory usage: 7.63 MB

# Boolean ones (True values) - great for masks
ones_bool = np.ones(5, dtype=bool)
print(ones_bool)
# Output: [ True  True  True  True  True]

# Complex numbers
ones_complex = np.ones(3, dtype=np.complex128)
print(ones_complex)
# Output: [1.+0.j 1.+0.j 1.+0.j]

My rule of thumb: use float32 for machine learning workloads (GPUs prefer it anyway), int32 or int64 for counting and indexing, and bool for masks. Only use float64 when you genuinely need the precision for scientific computing.

Creating Multi-Dimensional Arrays

For 3D and higher-dimensional arrays, pass a tuple with the appropriate number of elements:

import numpy as np

# 3D array for RGB image placeholder (height, width, channels)
image_placeholder = np.ones((256, 256, 3), dtype=np.uint8)
print(f"Shape: {image_placeholder.shape}")
print(f"Memory: {image_placeholder.nbytes / 1024:.2f} KB")
# Output:
# Shape: (256, 256, 3)
# Memory: 192.00 KB

# 4D array for batch of images (batch, height, width, channels)
batch_placeholder = np.ones((32, 224, 224, 3), dtype=np.float32)
print(f"Shape: {batch_placeholder.shape}")
print(f"Memory: {batch_placeholder.nbytes / 1024 / 1024:.2f} MB")
# Output:
# Shape: (32, 224, 224, 3)
# Memory: 14.44 MB

# 3D array for time series data (samples, timesteps, features)
time_series = np.ones((1000, 50, 10), dtype=np.float32)
print(f"Shape: {time_series.shape}")
# Output: Shape: (1000, 50, 10)

When working with image data, uint8 (unsigned 8-bit integer, 0-255 range) is the standard choice. For neural network inputs, float32 is typical since you’ll normalize pixel values to 0-1 or -1 to 1 ranges.

np.ones_like() for Matching Existing Arrays

When you need a ones array that matches an existing array’s shape and dtype, np.ones_like() is cleaner than extracting shape manually:

import numpy as np

# Original data array
data = np.array([[1.5, 2.3, 3.1],
                 [4.7, 5.2, 6.8]], dtype=np.float32)

# Create matching ones array - shape and dtype inherited
mask = np.ones_like(data)
print(mask)
# Output:
# [[1. 1. 1.]
#  [1. 1. 1.]]
print(mask.dtype)
# Output: float32

# Override dtype if needed
int_mask = np.ones_like(data, dtype=np.int32)
print(int_mask)
# Output:
# [[1 1 1]
#  [1 1 1]]

# Practical example: creating a weight mask
image = np.random.randint(0, 256, size=(100, 100, 3), dtype=np.uint8)
weight_mask = np.ones_like(image, dtype=np.float32)

# Now weight_mask has shape (100, 100, 3) and dtype float32
# Ready for element-wise multiplication with normalized image

The alternative—np.ones(data.shape, dtype=data.dtype)—works but is verbose and error-prone. I’ve seen bugs where developers forgot to copy the dtype, leading to precision loss or type mismatches.

Performance Considerations

The order parameter affects memory layout and can impact performance for certain operations:

import numpy as np

# C-order (row-major): rows are contiguous in memory
c_array = np.ones((1000, 1000), order='C')

# Fortran-order (column-major): columns are contiguous
f_array = np.ones((1000, 1000), order='F')

# Row operations are faster with C-order
# Column operations are faster with F-order

For most Python code, stick with the default 'C' order. Only switch to 'F' when interfacing with Fortran libraries or when your algorithm predominantly accesses data column-wise.

Here’s a comparison of array initialization strategies:

import numpy as np
import time

size = (5000, 5000)
iterations = 10

# Method 1: np.ones()
start = time.perf_counter()
for _ in range(iterations):
    arr = np.ones(size, dtype=np.float64)
ones_time = time.perf_counter() - start

# Method 2: np.empty() + fill()
start = time.perf_counter()
for _ in range(iterations):
    arr = np.empty(size, dtype=np.float64)
    arr.fill(1.0)
empty_fill_time = time.perf_counter() - start

# Method 3: np.full()
start = time.perf_counter()
for _ in range(iterations):
    arr = np.full(size, 1.0, dtype=np.float64)
full_time = time.perf_counter() - start

print(f"np.ones():        {ones_time:.4f}s")
print(f"np.empty()+fill(): {empty_fill_time:.4f}s")
print(f"np.full():        {full_time:.4f}s")

In practice, the differences are negligible for most applications. Use np.ones() for clarity. Only consider np.empty() when you’re immediately overwriting most values and profiling shows initialization as a bottleneck.

Practical Applications

Let’s look at real-world uses for ones arrays.

Bias Vector Initialization:

import numpy as np

# Simple linear layer: y = Wx + b
def linear_layer(x, weights, bias):
    return np.dot(x, weights) + bias

# Initialize bias to ones (common in some architectures)
input_size = 10
output_size = 5

weights = np.random.randn(input_size, output_size) * 0.01
bias = np.ones(output_size)  # Initialize bias to 1s

# Forward pass
x = np.random.randn(32, input_size)  # Batch of 32 samples
output = linear_layer(x, weights, bias)
print(f"Output shape: {output.shape}")
# Output: Output shape: (32, 5)

Creating Boolean Masks:

import numpy as np

# Start with all-True mask, then set conditions
data = np.array([1, 5, 3, 8, 2, 9, 4, 7])

# Initialize mask (all elements included)
mask = np.ones(len(data), dtype=bool)

# Exclude values less than 3
mask &= (data >= 3)

# Exclude values greater than 8
mask &= (data <= 8)

filtered = data[mask]
print(filtered)
# Output: [5 3 8 4 7]

Matrix Operations:

import numpy as np

# Create a matrix of ones for sum calculations
data = np.array([[1, 2, 3],
                 [4, 5, 6],
                 [7, 8, 9]])

# Sum each row using matrix multiplication with ones vector
ones_col = np.ones((3, 1))
row_sums = np.dot(data, ones_col)
print(row_sums.flatten())
# Output: [ 6. 15. 24.]

# Sum each column
ones_row = np.ones((1, 3))
col_sums = np.dot(ones_row, data)
print(col_sums.flatten())
# Output: [12. 15. 18.]

Normalizing Data:

import numpy as np

# Normalize each row to sum to 1
data = np.array([[1, 2, 3],
                 [4, 5, 6]], dtype=np.float32)

row_sums = data.sum(axis=1, keepdims=True)
normalized = data / row_sums

# Verify: each row should sum to 1
verification = np.ones((2,), dtype=np.float32)
print(np.allclose(normalized.sum(axis=1), verification))
# Output: True

The ones array is a fundamental building block. Master its parameters, understand when to use ones_like(), and choose appropriate dtypes. These small decisions compound into cleaner, more efficient numerical code.

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.