Python 時間波形をnumpyのスライスを使ってダウンサンプリングする方法

Programming
スポンサーリンク

はじめに

Pythonで1次元の numpy.ndarray 型の時間波形を扱っていて、処理の途中にスライスでダウンサンプリングしたいと思ったのですが、すぐに手実装ができず Chat GPT を使って実装したので、備忘録として記録しておきます。

コード

下記がコードです。2つの関数があります。

  • downsample は確実にインデックスが含まれる場合に使える関数
  • downsample_searchsorted は最も近いインデックスを取得してくれる関数
    • こちらの方が最も近いインデックスを探すために、データ数が多いと遅くなりがちのようです。
import timeit

import numpy as np


def downsample(t: np.ndarray, data: np.ndarray, t_downsample: np.ndarray) -> np.ndarray:
    """
    Perform downsampling on time series data using slicing.

    Parameters
    ----------
    t : numpy.ndarray
        Original time axis.
    data : numpy.ndarray
        Original data corresponding to the time axis.
    t_downsample : numpy.ndarray
        New time axis for downsampling.

    Returns
    -------
    numpy.ndarray
        Downsampled data.
    """
    indices = ((t_downsample - t[0]) / (t[1] - t[0])).astype(int)
    extracted_data = data[indices]
    return extracted_data


def downsample_searchsorted(
    t: np.ndarray, data: np.ndarray, t_downsample: np.ndarray
) -> np.ndarray:
    """
    Perform downsampling on time series data using np.searchsorted.

    Parameters
    ----------
    t : numpy.ndarray
        Original time axis.
    data : numpy.ndarray
        Original data corresponding to the time axis.
    t_downsample : numpy.ndarray
        New time axis for downsampling.

    Returns
    -------
    numpy.ndarray
        Downsampled data.
    """
    closest_indices = np.searchsorted(t, t_downsample)
    extracted_data = data[closest_indices]
    return extracted_data


# Generate original data
t_original = np.arange(0, 100000, 1)
data_original = t_original * 10

# Specify the range and step size for the new time axis for downsampling
start_value = 0
end_value = 10000
step_size = 2
t_downsample = np.arange(start_value, end_value, step_size)

# Measure the time taken by each function
time_downsample = timeit.timeit(
    lambda: downsample(t_original, data_original, t_downsample),
    number=100,
)
time_searchsorted = timeit.timeit(
    lambda: downsample_searchsorted(t_original, data_original, t_downsample),
    number=100,
)

print(f"t_original       : {t_original}")
print(f"data_original    : {data_original}")
print(f"t_downsample     : {t_downsample}")
print(f"data_downsample  : {downsample(t_original, data_original, t_downsample)}")
# t_original       : [    0     1     2 ... 99997 99998 99999]
# data_original    : [     0     10     20 ... 999970 999980 999990]
# t_downsample     : [   0    2    4 ... 9994 9996 9998]
# data_downsample  : [    0    20    40 ... 99940 99960 99980]

# Output the results
print(
    f"Time taken by downsample function: {time_downsample:.6f} seconds"
)  # 0.003711 seconds
print(
    f"Time taken by downsample_searchsorted function: {time_searchsorted:.6f} seconds"
)  # 0.032072 seconds

おわりに

備忘録として残しました。

コメント

タイトルとURLをコピーしました