На самом деле вы можете использовать scipy.interpolate.inter1d
для этого.
В качестве быстрого примера с квадратом:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
x = [0, 1, 1, 0, 0]
y = [0, 0, 1, 1, 0]
t = np.arange(len(x))
ti = np.linspace(0, t.max(), 10 * t.size)
xi = interp1d(t, x, kind='cubic')(ti)
yi = interp1d(t, y, kind='cubic')(ti)
fig, ax = plt.subplots()
ax.plot(xi, yi)
ax.plot(x, y)
ax.margins(0.05)
plt.show()
[/g0] / g5]
Однако, как вы можете видеть, это приводит к некоторым проблемам на 0,0.
Это происходит потому, что сегмент сплайна зависит не только от двух точек. Первая и последняя точки не «связаны» в том, как мы интерполировали. Мы можем исправить это путем «заполнения» последовательностей x и y со вторыми и последними и вторыми точками, так что существуют граничные условия «обматывания» для сплайна на конечных точках.
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
x = [0, 1, 1, 0, 0]
y = [0, 0, 1, 1, 0]
# Pad the x and y series so it "wraps around".
# Note that if x and y are numpy arrays, you'll need to
# use np.r_ or np.concatenate instead of addition!
orig_len = len(x)
x = x[-3:-1] + x + x[1:3]
y = y[-3:-1] + y + y[1:3]
t = np.arange(len(x))
ti = np.linspace(2, orig_len + 1, 10 * orig_len)
xi = interp1d(t, x, kind='cubic')(ti)
yi = interp1d(t, y, kind='cubic')(ti)
fig, ax = plt.subplots()
ax.plot(xi, yi)
ax.plot(x, y)
ax.margins(0.05)
plt.show()
[/g1]
И просто чтобы показать, как это выглядит с вашими данными:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
x = [-0.25, -0.625, -0.125, -1.25, -1.125, -1.25,
0.875, 1.0, 1.0, 0.5, 1.0, 0.625, -0.25]
y = [1.25, 1.375, 1.5, 1.625, 1.75, 1.875, 1.875,
1.75, 1.625, 1.5, 1.375, 1.25, 1.25]
# Pad the x and y series so it "wraps around".
# Note that if x and y are numpy arrays, you'll need to
# use np.r_ or np.concatenate instead of addition!
orig_len = len(x)
x = x[-3:-1] + x + x[1:3]
y = y[-3:-1] + y + y[1:3]
t = np.arange(len(x))
ti = np.linspace(2, orig_len + 1, 10 * orig_len)
xi = interp1d(t, x, kind='cubic')(ti)
yi = interp1d(t, y, kind='cubic')(ti)
fig, ax = plt.subplots()
ax.plot(xi, yi)
ax.plot(x, y)
ax.margins(0.05)
plt.show()
[/g2]
Обратите внимание, что вы получаете довольно «перерегулирование» с помощью этого метода. Это связано с кубической сплайновой интерполяцией. Предложение @ pythonstarter - еще один хороший способ справиться с этим, но кривые безье будут страдать от одной и той же проблемы (они в основном эквивалентны математически, это всего лишь вопрос о том, как определяются контрольные точки). Существует множество других способов обработки сглаживания, включая методы, которые предназначены для сглаживания многоугольника (например, полиномиальная аппроксимация с экспоненциальным ядром (PAEK)). Я никогда не пытался внедрить PAEK, поэтому я не уверен, как это связано. Если вам нужно сделать это более надежно, вы можете попробовать изучить PAEK или другой подобный метод.
Если вам просто нужно сдвинуть индекс на единицу, вы можете сделать это напрямую, не касаясь pd.Series
:
In [148]: df = pd.DataFrame([5, 10, 15, 12])
In [149]: df
Out[149]:
0
0 5
1 10
2 15
3 12
In [150]: df.index += 1
In [151]: df
Out[151]:
0
1 5
2 10
3 15
4 12