Python(或Excel)中的数据同步
我经常使用Python(偶尔也用Excel)来处理和比较多个实验的测试数据。有时候,数据可能不同步,这让直接比较变得困难。例如,一个典型的测试规范可能是:
1) Stabilize test temperature to a value of 20 +/- 2 degrees C
2) Hold test temperature at stabilized value for 15-25 seconds
3) Increase temperature by 20 degrees C at a rate of 0.5 degree C/second
将数据标准化,使它们在时间=0秒时都从20摄氏度开始是很简单的,但我真正想要的是让数据同步,这样温度上升的开始时间是一样的。
我尝试过一些简单的算法来检查数据的斜率,以找出温度开始上升的时刻,但由于仪器的原因,测量数据会有局部波动,这导致斜率并不能真实反映温度的整体变化率。
请问在Numpy、Scipy、Pandas等库中,有没有可以过滤这些局部波动并识别温度实际开始上升时刻的函数?
我偶尔也会用Excel,所以如果在电子表格中有更方便的方法来处理这些数据,我也可以用Excel来完成。
任何建议都非常感谢。
1 个回答
2
有很多方法可以解决这个问题。首先想到的是对数据进行数值微分,看看斜率从0跳到0.5的地方。但是(正如你观察到的)噪声数据可能会让这个方法效果不好。如果你在网上搜索“噪声数据的数值微分”,你会发现很多相关的研究,但我不知道在Python中有没有现成的库可以用。你可以尝试使用Savitzky-Golay滤波器:scipy.signal.savgol_filter
。
不过,这种方法可能有点复杂,因为你的信号有一个非常简单和特定的预期结构:先是一个恒定的区间,然后是一个上升段,最后又是一个恒定的区间。你可能会发现scipy.optimize.curve_fit
对这个问题效果很好。这里有一个例子:
from __future__ import division
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
def ramp(t, temp_init, temp_final, t0, t1):
slope = (temp_final - temp_init) / (t1 - t0)
y = temp_init + np.minimum(slope * np.maximum(t - t0, 0.0), temp_final - temp_init)
return y
np.random.seed(123)
dt = 0.5
t = np.arange(0, 100, dt)
# Generate a sample to work with.
temp_init = 20.0 + np.random.randn()
temp_final = 40.0 + np.random.randn()
t0 = 25.0
t1 = t0 + 40
y = ramp(t, temp_init, temp_final, t0, t1)
y += 0.25*np.random.randn(*t.shape) # Add noise.
# Create an initial guess for the four parameters and use curve_fit
# to fit the ramp function to the sample.
T = t[-1] - t[0]
p0 = (20, 40, t[0] + 0.333*T, t[0] + 0.667*T)
popt, pcov = curve_fit(ramp, t, y, p0=p0)
fit_temp_init, fit_temp_final, fit_t0, fit_t1 = popt
print " Input Fit"
print "temp_init %6.2f %6.2f" % (temp_init, fit_temp_init)
print "temp_final %6.2f %6.2f" % (temp_final, fit_temp_final)
print "t0 %6.2f %6.2f" % (t0, fit_t0)
print "t1 %6.2f %6.2f" % (t1, fit_t1)
plt.plot(t, y, 'ro', alpha=0.15)
plt.plot(t, ramp(t, popt[0], popt[1], popt[2], popt[3]), 'k-', linewidth=1.5)
plt.grid(True)
plt.xlabel('t', fontsize=12)
plt.show()
这会生成以下输出:
Input Fit
temp_init 18.91 18.91
temp_final 41.00 40.99
t0 25.00 24.85
t1 65.00 65.09
以及这个图: