Ever needed to generate 100 points between 0 and 1 for a smooth sine wave? Or create a color map for a heatmap? The solution is np.linspace(). This unassuming function is one of the most frequently used tools in the NumPy ecosystem, quietly powering everything from scientific computing to machine learning pipelines. In this guide, I'll walk you through everything you need to know about generating evenly spaced numbers with np.linspace — from the basic syntax to advanced use cases and the pitfalls that trip up even experienced developers.
Understanding np.linspace() Parameters: A Deep Dive
Let's start with the function signature, because once you understand what each parameter does, the rest falls into place naturally:
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)
The Core Arguments: start, stop, and num
The first three arguments are the ones you'll use 95% of the time. start is where your sequence begins, stop is where it ends, and num is how many evenly spaced numbers you want between them. The step size is automatically calculated — you never have to compute it yourself.
Here's what that looks like in practice:
import numpy as np
print(np.linspace(0, 10, 3))
print(np.linspace(0, 10, 4))
print(np.linspace(0, 10, 5))
Notice how the interval adjusts automatically. With num=3, the step is 5; with num=5, the step is 2.5. This is the fundamental difference from np.arange(), which I'll dig into later. The default value of num is 50, which is handy when you just need a quick set of points without thinking too hard about it.
Mastering endpoint and retstep for Precision Control
The endpoint parameter controls whether stop is included in the output. By default it's True, which means your array will include the stop value. Set it to False, and you get a sequence that approaches but never quite reaches stop.
print(np.linspace(0, 10, 5))
print(np.linspace(0, 10, 5, endpoint=False))
The mathematical relationship is straightforward:
- With
endpoint=True:step = (stop - start) / (num - 1) - With
endpoint=False:step = (stop - start) / num
I've found endpoint=False particularly useful when working with FFTs and signal processing, where you want exactly num samples per period without duplicating the boundary point.
The retstep parameter is a hidden gem. When set to True, it returns a tuple containing both the array and the step size:
result = np.linspace(0, 10, 5, retstep=True)
print(result)
print(np.linspace(0, 10, 5, retstep=True)[1])
This is incredibly useful when you need to verify your interval or pass it to another calculation. I've used this more times than I can count when debugging visualization code.
Controlling Data Type with dtype and Creating Multi-Dimensional Arrays
By default, np.linspace returns float64 values — even if you pass integers as arguments. If you need integers, use the dtype parameter:
print(np.linspace(0, 10, 3, dtype=int))
One thing to watch out for: when using dtype=int, the values are truncated, not rounded. So np.linspace(0, 10, 4, dtype=int) gives you [0, 3, 6, 10], not [0, 3, 7, 10].
For multi-dimensional arrays, np.linspace generates a 1D array, but you can reshape it easily:
print(np.linspace(0, 10, 12).reshape(3, 4))
This pattern — generate a linear sequence, then reshape — is surprisingly common in data preprocessing and feature engineering.
np.linspace vs np.arange vs np.logspace: Choosing the Right Tool
np.linspace vs np.arange: The Core Difference
This is probably the most common question I get from developers: "What's the difference between np.linspace and np.arange?" The answer comes down to what you're specifying:
np.arange(start, stop, step)— you specify the step size, and NumPy figures out how many elements you getnp.linspace(start, stop, num)— you specify the number of elements, and NumPy calculates the step
Here's a side-by-side comparison:
print(np.arange(0, 1, 0.2))
print(np.linspace(0, 1, 5))
| Function | You Specify | Step Calculation | Typical Use Case |
|---|---|---|---|
np.arange | Step size | Fixed | Simple counting, loops |
np.linspace | Number of points | Automatic | Plotting, sampling functions |
In my experience, np.linspace is almost always the better choice for plotting and data visualization. When you're generating x-values for a curve, you usually care about having enough points to make it smooth — not about the exact spacing. np.arange shines when you need precise control over the increment, like when iterating through a range of values. |
np.linspace vs np.logspace: Linear vs Logarithmic Spacing
While np.linspace gives you evenly spaced values on a linear scale, np.logspace generates values evenly spaced on a logarithmic scale. This is essential for frequency ranges in signal processing, where you might need decades of values.
print(np.linspace(0, 2, 5))
print(np.logspace(0, 2, 5))
Notice how np.logspace(0, 2, 5) gives you values from 10⁰ to 10², logarithmically spaced. This is invaluable when you're working with frequency responses, audio analysis, or any domain where values span multiple orders of magnitude.
Practical Applications: From Data Visualization to Machine Learning
Generating Smooth Curves for Data Visualization with Matplotlib
If you've ever plotted a sine wave that looked jagged or blocky, the culprit was probably too few data points. np.linspace solves this elegantly:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)
plt.plot(x, y)
plt.title('Sine Wave with np.linspace')
plt.xlabel('x')
plt.ylabel('sin(x)')
plt.grid(True)
plt.show()
The key insight here is that np.linspace guarantees your x-values span exactly the range you want, with no gaps or surprises. With np.arange, you might end up with 99 points instead of 100 due to floating-point rounding, which can subtly distort your plot.
Using np.linspace for Color Mapping and Data Generation
Beyond basic plotting, np.linspace is a workhorse for creating color maps and generating test data. For scatter plots where you want to encode a third variable as color:
import matplotlib.pyplot as plt
import numpy as np
x = np.random.rand(50)
y = np.random.rand(50)
colors = np.linspace(0, 1, 50) # Color values from 0 to 1
plt.scatter(x, y, c=colors, cmap='viridis', s=100)
plt.colorbar()
plt.show()
For machine learning, np.linspace is perfect for generating synthetic datasets. Need a linearly separable dataset for testing a classifier? Here's a quick approach:
X = np.linspace(0, 10, 20).reshape(-1, 1)
y = 2 * X.flatten() + 1 + np.random.randn(20) * 0.5
In signal processing, I regularly use np.linspace to generate time axes:
sample_rate = 1000 # Hz
duration = 2 # seconds
t = np.linspace(0, duration, sample_rate * duration, endpoint=False)
This gives you exactly 2000 samples over 2 seconds, which is precisely what you need for FFT analysis.
Troubleshooting and Advanced Tips: Solving Common Issues
Why is My np.linspace Not Evenly Spaced? (Floating Point Precision)
Here's a subtle issue that's bitten me more than once: floating-point arithmetic can introduce tiny errors that make the last element slightly different from what you expect. This is the "np.linspace not evenly spaced" problem that shows up in forums.
arr = np.linspace(0, 1, 3)
print(arr)
arr2 = np.linspace(0, 0.3, 4)
print(arr2)
This happens because binary floating-point can't represent all decimal numbers exactly. The fix depends on your use case:
arr = np.linspace(0, 1, 5, endpoint=False)
arr = np.round(np.linspace(0, 1, 5), 10)
arr = np.linspace(0, np.nextafter(1, 2), 5)
In most practical applications, these tiny errors don't matter. But if you're comparing values with == or using them as dictionary keys, they can cause real headaches.
How to Specify Start, Step, and Number? (The np.arange Alternative)
A common question I see is: "Is there a NumPy function that lets me specify start, step, and number of elements?" np.linspace doesn't directly support this, but you can easily achieve it:
def linspace_step(start, step, num):
"""Generate num points starting at start with given step."""
stop = start + step * (num - 1)
return np.linspace(start, stop, num)
print(linspace_step(0, 2, 5))
This gives you the best of both worlds — the precision of specifying a step with the reliability of np.linspace. I've wrapped this in a utility function in several projects, and it's saved me from countless off-by-one errors.
Frequently Asked Questions
What is the difference between np.linspace and np.arange?
np.arange creates an array based on a specified step size, while np.linspace creates an array based on a specified number of elements. For example, np.arange(0, 1, 0.2) gives you [0, 0.2, 0.4, 0.6, 0.8], while np.linspace(0, 1, 5) gives you [0, 0.25, 0.5, 0.75, 1]. Use np.linspace when you need a specific number of points, and np.arange when you need a specific step size.
Can np.linspace generate integers?
Yes, by using the dtype=int parameter: np.linspace(0, 10, 5, dtype=int) returns [0, 2, 5, 7, 10]. Note that values are truncated, not rounded, and the default dtype is float64.
What is the purpose of the 'retstep' parameter in np.linspace?
When retstep=True, np.linspace returns a tuple containing the generated array and the step size. For example, np.linspace(0, 10, 5, retstep=True) returns (array([0., 2.5, 5., 7.5, 10.]), 2.5). This is useful when you need to verify the interval or use it in subsequent calculations.
How to create a 2D array using np.linspace?
np.linspace generates a 1D array, but you can use the reshape() method to convert it: np.linspace(0, 10, 12).reshape(3, 4) creates a 3×4 array with values evenly spaced from 0 to 10.
Conclusion
np.linspace is one of those functions that seems simple on the surface but reveals its depth the more you use it. Whether you're generating smooth curves for visualization, creating test data for machine learning models, or building time axes for signal processing, it's an indispensable tool in the NumPy ecosystem.
The key takeaways: understand the difference between specifying num versus step, remember that endpoint and retstep give you precise control, and be aware of floating-point precision issues when they matter. And when you need logarithmic spacing, np.logspace has you covered.
I've been using np.linspace for over a decade, and it still surprises me with new use cases. I'd love to hear how you're using it in your projects — drop a comment below and share your favorite np.linspace tricks. And if you're just getting started with NumPy, I encourage you to experiment with the code examples here and explore what else this powerful library has to offer.




