matplotlib 在同一点重叠图形

fnatzsnv  于 2022-11-30  发布在  其他
关注(0)|答案(1)|浏览(211)

我想从CSV数据(两个数据集)中叠加一些图表。我从我的数据集中得到的图表如下所示。
有没有办法把这些数据集绘制在特定的点上?我想通过使用“大落差”的锚来覆盖这些图,以便以更好的方式进行比较。
使用的代码:

import pandas as pd
import matplotlib.pyplot as plt

# Read the data
data1 = pd.read_csv('data1.csv', delimiter=";", decimal=",")
data2 = pd.read_csv('data2.csv', delimiter=";", decimal=",")
data3 = pd.read_csv('data3.csv', delimiter=";", decimal=",")
data4 = pd.read_csv('data4.csv', delimiter=";", decimal=",")

# Plot the data
plt.plot(data1['Zeit'], data1['Kanal A'])
plt.plot(data2['Zeit'], data2['Kanal A'])
plt.plot(data3['Zeit'], data3['Kanal A'])
plt.plot(data4['Zeit'], data4['Kanal A'])

plt.show()
plt.close()

我想在这里与大家分享一些数据:Link to data

zpf6vheq

zpf6vheq1#

第1部分:锚时间

一个简单的方法是找到每个帧中感兴趣的时间(最低点),然后用x=t - t_peak而不是x=t来绘制每个序列。有两种方法可以找到所需的锚点:
1.仅使用全局最小值(在图中,这将很好地工作),或
1.使用最显著的局部最小值,或者根据第一原理,或者使用scipy的find_peaks()
但首先,让我们尝试建立一个可复制的示例

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

def make_sample(t_peak, tmax_approx=17.5, n=100):
    # uneven times
    t = np.random.uniform(0, 2*tmax_approx/n, n).cumsum()
    y = -1 / (0.1 + 2 * np.abs(t - t_peak))
    trend = 4 * np.random.uniform(-1, 1) / n
    level = np.random.uniform(10, 12)
    y += np.random.normal(trend, 1/n, n).cumsum() + level
    return pd.DataFrame({'t': t, 'y': y})

poi = [2, 2.48, 2.6, 2.1]

np.random.seed(0)
frames = [make_sample(t_peak) for t_peak in poi]

plt.rcParams['figure.figsize'] = (6,2)
fig, ax = plt.subplots()
for df in frames:
    ax.plot(*df.values.T)

在这种情况下,我们通过给每个时间序列自己的、独立的、不均匀分布的时间采样,使问题变得最不方便。
现在,通过全局最小值检索“最大落差”:
第一次
但是想象一下全局最小值不适用的情况。例如,向每个系列添加一个大正弦波:

frames = [df.assign(y=df['y'] + 5 * np.sin(df['t'])) for df in frames]

# just plotting the first series
df = frames[0]
plt.plot(*df.values.T)

很明显,有几个局部最小值,而我们想要的那个(“最陡的下降”)不是全局最小值。
找到所需的最陡下降时间的简单方法是查看每个点与其两个相邻点之间的差异:
第一次
在更复杂的情况下,您需要充分利用find_peaks()的功能。下面是一个使用最显著最小值的示例,使用一定数量的样本作为邻域:

from scipy.signal import find_peaks, peak_prominences

def arg_most_prominent_min(v, prominence=1, wlen=10):
    peaks, details = find_peaks(-v, prominence=prominence, wlen=wlen)
    i = peaks[np.argmax(details['prominences'])]
    return i

peaks = [df['t'].iloc[arg_most_prominent_min(df['y'])] for df in frames]
>>> peaks
[2.0209774600118764, 2.4932468358014157, 2.5835972003585472, 2.12438578790615]

在这种情况下,两种方法找到的峰是相同的。对齐曲线得到:

fig, ax = plt.subplots()
for t_peak, df in zip(peaks, frames):
    ax.plot(df['t'] - t_peak, df['y'])


文件系统

第2部分:对齐数值运算的时间序列

在找到锚时间并通过相应地移动x轴来绘制时间序列之后,假设现在我们想要 * 对齐 * 所有时间序列,例如以某种方式将它们彼此进行比较(例如:差异、相关性等)。在我们所做的这个例子中,时间样本不是等距的,所有序列都有自己的采样。
我们可以使用resample()来实现我们的目标。让我们将帧转换为实际的时间序列,将列t(假设以秒为单位)转换为DateTimeIndex,然后使用先前找到的t_peak和任意的“0”日期来移动时间:

frames = [
    pd.Series(
        df['y'].values,
        index=pd.Timestamp(0) + (df['t'] - t_peak) * pd.Timedelta(1, 's')
    ) for t_peak, df in zip(peaks, frames)]
>>> frames[0]
t
1969-12-31 23:59:58.171107267    11.244308
1969-12-31 23:59:58.421423545    12.387291
1969-12-31 23:59:58.632390727    13.268186
1969-12-31 23:59:58.823099841    13.942224
1969-12-31 23:59:58.971379021    14.359900
                                   ...    
1970-01-01 00:00:14.022717327    10.422229
1970-01-01 00:00:14.227996854     9.504693
1970-01-01 00:00:14.235034496     9.489011
1970-01-01 00:00:14.525163506     8.388377
1970-01-01 00:00:14.526806922     8.383366
Length: 100, dtype: float64

此时,采样仍然是不均匀的,因此我们使用重采样来获得固定的频率。一种策略是过采样和插值:

frames = [df.resample('100ms').mean().interpolate() for df in frames]

for df in frames:
    df.plot()


文件系统
此时,我们可以比较数列。下面是两两之间的差异和相关系数:

fig, axes = plt.subplots(nrows=len(frames), ncols=len(frames), figsize=(10, 5))
for axrow, a in zip(axes, frames):
    for ax, b in zip(axrow, frames):
        (b-a).plot(ax=ax)
        ax.set_title(fr'$\rho = {b.corr(a):.3f}$')
        ax.get_xaxis().set_visible(False)
        ax.get_yaxis().set_visible(False)
plt.tight_layout()


文件系统

相关问题