Если у меня есть этот массив NumPy:
x = np.array([10,20])
, и я хочу «растянуть» его, удвоив его размер, я могу очень легко сделать это с помощью
y = np.repeat(x,2)/2
и получить
[5,5,10,10]
Однако, что, если я хочу растянуть его, добавив не 2, а произвольное количество периодов? Это как если бы я хотел повторить нецелое число в формулевыше.
Основанием для этого является то, что у меня есть массив, который измеряет что-то с течением времени - например, каждый элемент массива - это расстояние, пройденное за один период.
Мне нужно«растянуть» массив, например, вычислить новый массив, где пройдено такое же расстояние, скажем, в 30 периодах вместо 20. Мне нужно, чтобы процентили были одинаковыми, чтобы общее пройденное расстояние было одинаковым, суммапервые 10 элементов в первом массиве = сумма первых 15 в новом массиве и т. д.
Линейная интерполяция в порядке.
Я что-то придумал вместе с scipy.interpolate
но это кажется немного запутанным, и я былNdering, если есть лучший способ.Шаги:
- Я начинаю с моего массива y Я устанавливаю x в качестве соответствующего индекса%, так что 1-й элемент равен 1 / длина, а последний = 100%
- Iдобавить ноль в начале ox и x и y (чтобы избежать интерполяции ниже ошибки диапазона)
- Я интерполирую накопленную сумму
- Я использую интерполированную функцию для вычисления «растянутого» массива
Код такой. РЕДАКТИРОВАТЬ : Я изучил ответ @eliadl.Это очень близко к моему, но не на 100% идентично.Мне непонятно, в чем причина разницы - приветствуется любая информация!
Я собрал код ниже, чтобы показать различия.Мой код достигает того, что я имел в виду: если в исходном массиве было 4 элемента, а в новом 10 и CDF (накопительная функция распределения) = 40% для второго элемента, то CDF должен = 40% для 5-го элементановый массив и т. д.
import numpy as np
import pandas as pd
import scipy
import matplotlib.pyplot as plt
import matplotlib
import seaborn
import seaborn as sns
from matplotlib.ticker import FuncFormatter
sns.set(style='darkgrid')
def my_stretch(inp, s):
y = inp
x = np.arange(1, len(y) +1 ) / len(y)
y_2 = np.hstack([0,y])
x_2 = np.hstack([0,x])
f_int = scipy.interpolate.interp1d(x_2 , np.cumsum(y_2) )
x_new = np.arange(0, len(y) + s + 1 ) / ( len(y) + s )
y_new_cum = f_int(x_new)
y_new = np.diff(y_new_cum)
return y_new
def your_stretch(inp,s):
x = np.arange(y.size)
x_stretch = np.linspace(x[0], x[-1], num = x.size + s )
y_stretch = np.interp(x_stretch, x, y)
y_stretch *= y.sum() / y_stretch.sum()
return y_stretch
def cdf(x):
return np.cumsum(x) / x.sum()
y = np.array([20,10,8,6,4,2])
s = 3
my_s = my_stretch(y,s)
your_s = your_stretch(y,s)
cdf_orig = cdf(y)
cdf_my = cdf(my_s)
cdf_your = cdf(your_s)
fig, ax = plt.subplots(2,1)
sns.lineplot( np.arange(1,len(my_s) + 1 ) / len(my_s) , cdf_my, label = 'mine', marker='o', ax = ax[0] )
sns.lineplot( np.arange(1,len(your_s) + 1)/len(your_s) , cdf_your, label = 'yours', marker ='o', ax = ax[0] )
sns.lineplot( np.arange(1,len(y) + 1 ) / len(y) , cdf_orig, label = 'original', ax = ax[0] )
ax[1].plot( my_s , label = 'mine' , marker='o' )
ax[1].plot(your_s, label = 'yours', marker='o')
ax[0].set_xlabel('% position (the last item in the array = 1 ↑')
ax[0].set_ylabel('cumulative distribution function')
ax[1].set_xlabel('item in the array ↑')
ax[1].set_ylabel('value')
ax[1].legend()