Skip to content
주제
NumPy
NumPy Linspace: Python에서 균등 간격 배열을 만드는 방법

NumPy Linspace: Python에서 균등 간격 배열을 만드는 방법

Updated on

균등 간격의 숫자 시퀀스를 생성하는 것은 시작, 끝, 개수에 대한 정확한 제어가 필요해질 때까지는 간단해 보입니다. Python의 내장 range()는 정수만 처리하며, numpy.arange()도 부동소수점 스텝 크기가 반올림 오류를 누적하면 예상치 못한 결과를 낼 수 있습니다. 함수를 플롯했는데 들쭉날쭉한 곡선이 나오거나 마지막 x값이 빠진 경험이 있다면, 바로 이 문제를 겪은 것입니다. numpy.linspace()는 이를 해결하기 위해 존재합니다: 두 끝점 사이에 몇 개의 점을 원하는지 지정하면, NumPy가 정확한 간격을 계산해줍니다.

📚

이 가이드에서는 np.linspace()의 전체 API를 배우고, np.arange()와의 비교를 확인하며, 매끄러운 곡선 그리기부터 다차원 그리드 구축까지 실제 사용 사례를 살펴봅니다. 모든 코드 예제는 복사-붙여넣기가 가능하며 출력 결과를 보여줍니다.

np.linspace()는 무엇을 하나요?

numpy.linspace()는 지정된 구간에 걸쳐 균등 간격의 숫자 배열을 반환합니다. 핵심 아이디어는 스텝 크기가 아닌 샘플 수를 정의한다는 것입니다.

전체 시그니처

numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)
매개변수타입기본값설명
startfloat 또는 array-like필수구간의 시작
stopfloat 또는 array-like필수구간의 끝
numint50생성할 샘플 수
endpointboolTrue출력에 stop을 포함할지 여부
retstepboolFalseTrue이면 스텝 크기도 반환
dtypedtypeNone출력 배열의 데이터 타입 (None이면 추론)
axisint0샘플을 저장할 축 (start/stop이 배열일 때 관련)

기본 예제

import numpy as np
 
arr = np.linspace(0, 1, 5)
print(arr)
# Output: [0.   0.25 0.5  0.75 1.  ]

NumPy는 구간 [0, 1]을 4개의 동일한 간격(요청한 5개 점보다 1개 적음)으로 나누고, 양 끝점을 포함한 5개의 경계값을 모두 반환합니다.

num으로 점의 수 제어하기

num 매개변수는 반환되는 배열에 몇 개의 값이 포함되는지를 결정합니다. 기본값은 50이므로, np.linspace(0, 10)을 호출하면 명시적으로 요청하지 않아도 50개의 값을 얻게 됩니다.

import numpy as np
 
# 0과 10 사이에 3개 점
print(np.linspace(0, 10, num=3))
# Output: [ 0.  5. 10.]
 
# -1과 1 사이에 6개 점
print(np.linspace(-1, 1, num=6))
# Output: [-1.  -0.6 -0.2  0.2  0.6  1. ]

흔한 실수는 num=1로 설정하는 것입니다. 이 경우 start 값만 반환됩니다.

import numpy as np
 
print(np.linspace(0, 10, num=1))
# Output: [0.]

endpoint 매개변수: 끝값 포함 또는 제외

기본적으로 endpoint=True이며, stop 값이 배열의 마지막 요소가 됩니다. endpoint=False로 설정하면 끝값이 제외되고 간격이 변경됩니다.

import numpy as np
 
with_endpoint = np.linspace(0, 1, 5, endpoint=True)
print("endpoint=True: ", with_endpoint)
# Output: endpoint=True:  [0.   0.25 0.5  0.75 1.  ]
 
without_endpoint = np.linspace(0, 1, 5, endpoint=False)
print("endpoint=False:", without_endpoint)
# Output: endpoint=False: [0.  0.2 0.4 0.6 0.8]
설정스텝 공식마지막 값
endpoint=True(stop - start) / (num - 1)정확히 stop
endpoint=False(stop - start) / numstop 한 스텝 전

endpoint=False는 언제 유용할까요? 대표적인 예는 이산 푸리에 변환용 각도를 생성할 때입니다. 시작 각도를 반복하지 않으면서 [0, 2*pi)에 N개의 점이 필요한 경우에 사용합니다.

import numpy as np
 
N = 8
angles = np.linspace(0, 2 * np.pi, N, endpoint=False)
print(np.round(angles, 4))
# Output: [0.     0.7854 1.5708 2.3562 3.1416 3.927  4.7124 5.4978]

retstep으로 스텝 크기 얻기

retstep=True일 때, np.linspace()는 튜플을 반환합니다: 배열과 계산된 스텝 크기입니다. 나중의 계산에 간격이 필요하지만 직접 계산하고 싶지 않을 때 유용합니다.

import numpy as np
 
values, step = np.linspace(0, 10, num=5, retstep=True)
print("Values:", values)
print("Step:  ", step)
# Output:
# Values: [ 0.   2.5  5.   7.5 10. ]
# Step:   2.5

스텝 크기는 수치 미분, 적분, 또는 그리드가 기대하는 해상도를 갖는지 확인하는 데 사용할 수 있습니다.

import numpy as np
 
x, dx = np.linspace(0, np.pi, 1000, retstep=True)
# Approximate integral of sin(x) from 0 to pi using the trapezoidal rule
integral = np.trapz(np.sin(x), dx=dx)
print(f"Integral of sin(x) over [0, pi]: {integral:.6f}")
# Output: Integral of sin(x) over [0, pi]: 2.000000

np.linspace() vs np.arange(): 언제 어떤 것을 사용할까

두 함수 모두 숫자 시퀀스를 생성하지만, 근본적으로 다릅니다: linspace개수를 지정하고, arange스텝 크기를 지정합니다.

특징np.linspace()np.arange()
지정하는 것점의 수 (num)스텝 크기 (step)
끝점 포함?기본적으로 예포함 안 함 (배타적 stop)
부동소수점 스텝 정밀도정확 (구간을 나눔)반올림 오류가 누적될 수 있음
일반적인 용도플롯, 보간정수 범위, 반복
스텝 크기 반환?retstep=True로 가능아니오 (이미 알고 있음)

arange의 부동소수점 함정

import numpy as np
 
# arange can produce unexpected element counts with float steps
arr = np.arange(0, 1, 0.1)
print(len(arr), arr)
# Output: 10 [0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]
 
# Slightly different bounds can cause an extra element
arr2 = np.arange(0, 1.0 + 1e-15, 0.1)
print(len(arr2))
# Output: 11

linspace를 사용하면 항상 요청한 정확한 수의 요소를 얻습니다. 부동소수점 구간을 다룰 때는 특정 스텝 크기와 정수 친화적인 경계가 정말로 필요한 경우가 아니라면 linspace를 선택하세요.

실용적인 사용 사례

1. 매끄러운 곡선 플롯

np.linspace()의 가장 일반적인 용도는 수학 함수를 플롯하기 위한 x값을 생성하는 것입니다. 점이 많을수록 더 매끄러운 곡선이 됩니다.

import numpy as np
import matplotlib.pyplot as plt
 
x = np.linspace(-2 * np.pi, 2 * np.pi, 300)
y = np.sin(x) / x  # sinc-like function (warning: division by zero at x=0)
 
# Handle division by zero
y = np.where(np.isclose(x, 0), 1.0, np.sin(x) / x)
 
plt.figure(figsize=(8, 4))
plt.plot(x, y, linewidth=1.5)
plt.title("sinc-like function: sin(x)/x")
plt.xlabel("x")
plt.ylabel("y")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig("sinc_plot.png", dpi=100)
plt.show()

2. 신호 처리: 시간 축 생성

신호를 시뮬레이션하거나 분석할 때, 알려진 샘플링 레이트를 가진 시간 벡터가 필요합니다. linspace를 사용하면 간단하게 만들 수 있습니다.

import numpy as np
 
duration = 1.0        # seconds
sample_rate = 44100   # Hz (CD quality)
num_samples = int(duration * sample_rate)
 
t = np.linspace(0, duration, num_samples, endpoint=False)
 
# Generate a 440 Hz sine wave (concert A)
frequency = 440
signal = np.sin(2 * np.pi * frequency * t)
 
print(f"Time array shape: {t.shape}")
print(f"First 5 time values: {t[:5]}")
print(f"First 5 signal values: {np.round(signal[:5], 6)}")
# Output:
# Time array shape: (44100,)
# First 5 time values: [0.00000000e+00 2.26757370e-05 4.53514739e-05 6.80272109e-05 9.07029478e-05]
# First 5 signal values: [0.       0.062648 0.125178 0.187474 0.24942 ]

여기서 endpoint=False가 사용된 이유는 신호가 주기적이기 때문입니다: t = 1.0의 샘플은 t = 0.0의 샘플과 중복됩니다.

3. 색상 그래디언트 만들기

linspace는 사용자 정의 컬러맵을 만들 때 색상 값 사이를 보간하는 데 유용합니다.

import numpy as np
 
# Interpolate between blue (0, 0, 255) and red (255, 0, 0) in 5 steps
steps = 5
r = np.linspace(0, 255, steps).astype(int)
g = np.zeros(steps, dtype=int)
b = np.linspace(255, 0, steps).astype(int)
 
colors = np.column_stack([r, g, b])
for i, c in enumerate(colors):
    print(f"Step {i}: RGB({c[0]:3d}, {c[1]:3d}, {c[2]:3d})")
# Output:
# Step 0: RGB(  0,   0, 255)
# Step 1: RGB( 63,   0, 191)
# Step 2: RGB(127,   0, 127)
# Step 3: RGB(191,   0,  63)
# Step 4: RGB(255,   0,   0)

linspace와 meshgrid를 이용한 다차원 그리드

2D 또는 3D 계산(히트맵, 표면 플롯, 등고선 플롯)에서는 np.linspace()np.meshgrid()를 결합합니다.

import numpy as np
 
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x, y)
 
# Compute a 2D Gaussian
Z = np.exp(-(X**2 + Y**2))
 
print(f"X shape: {X.shape}")
print(f"Z min: {Z.min():.6f}, Z max: {Z.max():.6f}")
# Output:
# X shape: (100, 100)
# Z min: 0.000001, Z max: 1.000000
import numpy as np
import matplotlib.pyplot as plt
 
x = np.linspace(-3, 3, 200)
y = np.linspace(-3, 3, 200)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X**2 + Y**2))
 
plt.figure(figsize=(6, 5))
plt.contourf(X, Y, Z, levels=20, cmap="viridis")
plt.colorbar(label="Amplitude")
plt.title("2D Gaussian via linspace + meshgrid")
plt.xlabel("x")
plt.ylabel("y")
plt.tight_layout()
plt.savefig("gaussian_contour.png", dpi=100)
plt.show()

이 패턴은 어떤 차원으로도 확장할 수 있습니다. 3D 그리드의 경우 세 번째 linspace 호출을 추가하고 np.meshgrid(x, y, z)를 사용합니다.

dtype 매개변수

기본적으로 np.linspace()float64 값을 반환합니다. dtype 매개변수로 이를 변경할 수 있지만, 정수 타입은 계산된 값을 잘라낸다는 점에 유의하세요.

import numpy as np
 
# Float64 (default)
print(np.linspace(0, 5, 6).dtype)
# Output: float64
 
# Explicit float32 for memory savings
arr32 = np.linspace(0, 1, 5, dtype=np.float32)
print(arr32, arr32.dtype)
# Output: [0.   0.25 0.5  0.75 1.  ] float32
 
# Integer dtype truncates values
arr_int = np.linspace(0, 10, 5, dtype=int)
print(arr_int)
# Output: [ 0  2  5  7 10]

정수 dtype을 사용하면 소수 부분이 단순히 버려져(floor 동작) 불균등한 간격의 결과를 생성할 수 있습니다. 변환할 특별한 이유가 없다면 float 타입을 유지하세요.

일반적인 패턴: 함수 플롯을 위한 X값 생성

반복적으로 사용하게 될 패턴들의 간결한 참고 자료입니다.

패턴 1: 표준 함수 플롯

import numpy as np
import matplotlib.pyplot as plt
 
x = np.linspace(0, 10, 500)
plt.plot(x, np.sin(x), label="sin(x)")
plt.plot(x, np.cos(x), label="cos(x)")
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

패턴 2: 매개변수 곡선

import numpy as np
import matplotlib.pyplot as plt
 
t = np.linspace(0, 2 * np.pi, 1000)
x = 16 * np.sin(t)**3
y = 13 * np.cos(t) - 5 * np.cos(2*t) - 2 * np.cos(3*t) - np.cos(4*t)
 
plt.figure(figsize=(5, 5))
plt.plot(x, y, color="red")
plt.title("Heart Curve")
plt.axis("equal")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

패턴 3: 범위에 걸쳐 다항식 평가

import numpy as np
 
coefficients = [1, -3, 2]  # x^2 - 3x + 2
x = np.linspace(-1, 4, 6)
y = np.polyval(coefficients, x)
 
for xi, yi in zip(x, y):
    print(f"x={xi:5.2f}  ->  y={yi:5.2f}")
# Output:
# x=-1.00  ->  y= 6.00
# x= 0.00  ->  y= 2.00
# x= 1.00  ->  y= 0.00
# x= 2.00  ->  y= 0.00
# x= 3.00  ->  y= 2.00
# x= 4.00  ->  y= 6.00

PyGWalker로 Linspace 생성 데이터 시각화하기

np.linspace()로 만든 배열을 다룰 때, 결과 데이터를 인터랙티브하게 탐색해야 하는 경우가 자주 있습니다 -- 축을 조정하거나 범위를 필터링하거나 매번 플롯 코드를 다시 작성하지 않고 여러 시리즈를 비교하는 것 말입니다. PyGWalker (opens in a new tab)는 어떤 Pandas DataFrame이든 Jupyter Notebook 내에서 직접 Tableau와 유사한 인터랙티브 시각화 인터페이스로 변환하는 오픈소스 Python 라이브러리입니다.

linspace로 생성한 데이터를 PyGWalker와 결합하여 인터랙티브하게 탐색하는 방법은 다음과 같습니다:

import numpy as np
import pandas as pd
import pygwalker as pyg
 
# Generate data using linspace
x = np.linspace(0, 4 * np.pi, 200)
df = pd.DataFrame({
    "x": x,
    "sin": np.sin(x),
    "cos": np.cos(x),
    "damped_sin": np.exp(-0.1 * x) * np.sin(x),
})
 
# Launch interactive visualization in Jupyter
walker = pyg.walk(df)

PyGWalker를 열면 x를 x축으로 드래그하고, sindamped_sin을 y축에 놓아 파형을 즉시 비교할 수 있습니다. 추가 코드를 작성하지 않고도 라인 차트, 산점도, 막대 차트 사이를 전환할 수 있습니다. 이는 linspace로 다양한 매개변수 범위의 데이터를 생성하고 최종 플롯에 확정하기 전에 동작을 시각적으로 확인하고 싶을 때 특히 유용합니다.

자주 묻는 질문

np.linspace와 np.arange의 차이점은 무엇인가요?

np.linspace()는 시작값, 끝값, 그리고 원하는 점의 수를 받습니다. np.arange()는 시작값, 끝값, 그리고 스텝 크기를 받습니다. 점의 수가 중요할 때(플롯, 보간)는 linspace를 사용하세요. 값 사이의 정확한 스텝이 중요할 때(정수 시퀀스, 루프)는 arange를 사용하세요.

np.linspace는 기본적으로 끝점을 포함하나요?

네. 기본적으로 endpoint=True이므로, stop 값이 마지막 요소로 포함됩니다. 주기적 신호나 푸리에 변환에서 제외하려면 endpoint=False로 설정하세요.

np.linspace에서 스텝 크기를 얻으려면 어떻게 하나요?

retstep=True를 전달하면 (배열, 스텝_크기) 튜플을 얻습니다. 예: values, step = np.linspace(0, 10, 100, retstep=True).

np.linspace로 정수를 생성할 수 있나요?

dtype=int를 전달할 수 있지만, 값이 잘려서(반올림이 아님) 종종 불균등한 간격이 됩니다. 균등 간격의 정수가 필요하다면 np.arange()가 보통 더 나은 선택입니다.

매끄러운 플롯에는 몇 개의 점을 사용해야 하나요?

대부분의 2D 함수 플롯에서 200~500개의 점으로 시각적으로 매끄러운 곡선을 얻을 수 있습니다. 고주파 함수나 출판 품질의 그림에는 1000개의 점이 안전한 선택입니다. 점이 많아지면 메모리 사용량과 렌더링 시간이 증가하므로, 매끄러움과 성능 사이의 균형을 맞추세요.

결론

numpy.linspace()가 가장 자주 사용되는 NumPy 함수 중 하나인 이유는 분명합니다: 두 끝점 사이에 생성하는 균등 간격 값의 수를 정확하게 제어할 수 있기 때문입니다. np.arange()와 달리, 부동소수점 반올림으로 인해 추가 요소가 생기거나 요소가 빠지는 일이 절대 없습니다. endpoint, retstep, dtype 매개변수는 빠른 플롯에서 신호 처리 파이프라인까지 모든 것에 대한 세밀한 제어를 제공합니다.

핵심 요약:

  • num을 사용하여 출력 값의 정확한 수를 설정하세요.
  • 끝값이 시작값과 중복되는 주기적 데이터에는 endpoint=False를 설정하세요.
  • 후속 계산에 스텝 크기가 필요할 때마다 retstep=True를 사용하세요.
  • 부동소수점 구간에서는 arange보다 linspace를 선호하세요.
  • 다차원 그리드를 위해 linspacemeshgrid를 결합하세요.

이러한 패턴을 도구 상자에 갖추면, Python에서 플롯, 시뮬레이션, 보간, 과학 컴퓨팅을 위한 수치 시퀀스를 자신 있게 생성할 수 있습니다.

📚