关于Python:Python – 在绘图中查找模式

Python - finding pattern in a plot

enter image description here

此图由以下gnuplot脚本生成。estimated.csv文件位于以下链接中:https://drive.google.com/open?ID=0B2IV8DFU4TUAGRWMM9JWNBUBZG

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# ###### GNU Plot
   set style data lines
   set terminal postscript eps enhanced color"Times" 20

   set output"cubic33_cwd_estimated.eps"

   set title"Estimated signal"

    set style line 99 linetype 1 linecolor rgb"#999999" lw 2
    #set border 1 back ls 11
    set key right top
    set key box linestyle 50
    set key width -2
    set xrange [0:10]
    set key spacing 1.2
    #set nokey

    set grid xtics ytics mytics
    #set size 2
    #set size ratio 0.4

    #show timestamp
    set xlabel"Time [Seconds]"
    set ylabel"Segments"

    set style line 1 lc rgb"#ff0000" lt 1 pi 0 pt 4 lw 4 ps 0

    # Congestion control send window

    plot "estimated.csv" using ($1):2 with lines title"Estimated";

我想找到前一个图的估计信号的模式,接近下面的图。我的地面实况(实际信号如下图所示)enter image description here

这是我的初步方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python
import sys

import numpy as np
from shapely.geometry import LineString
#-------------------------------------------------------------------------------
def load_data(fname):
    return LineString(np.genfromtxt(fname, delimiter = ','))
#-------------------------------------------------------------------------------
lines = list(map(load_data, sys.argv[1:]))

for g in lines[0].intersection(lines[1]):
    if g.geom_type != 'Point':
        continue
    print('%f,%f' % (g.x, g.y))

然后在我的gnuplot中直接调用这个python脚本,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
set terminal pngcairo
set output 'fig.png'

set datafile separator comma
set yr [0:700]
set xr [0:10]

set xtics 0,2,10
set ytics 0,100,700

set grid

set xlabel"Time [seconds]"
set ylabel"Segments"

plot \
    'estimated.csv' w l lc rgb 'dark-blue' t 'Estimated', \
    'actual.csv' w l lc rgb 'green' t 'Actual', \
    '<python filter.py estimated.csv actual.csv' w p lc rgb 'red' ps 0.5 pt 7 t ''

这给了我们下面的情节。但这似乎并没有给我正确的模式,因为gnuplot不是此类任务的最佳工具。

氧化镁

有没有什么方法可以通过使用python将峰值形成一个图来找到第一个图(estimated.csv)的模式?如果我们从最后看到,模式实际上似乎是可见的。任何帮助都将不胜感激。


我认为pandas.rolling_max()是正确的方法。我们正在将数据加载到数据帧中,并计算超过8500个值的滚动最大值。之后,曲线看起来很相似。您可以对参数进行一点测试以优化结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
plt.ion()
names = ['actual.csv','estimated.csv']
#-------------------------------------------------------------------------------
def load_data(fname):
    return np.genfromtxt(fname, delimiter = ',')
#-------------------------------------------------------------------------------

data = [load_data(name) for name in names]
actual_data = data[0]
estimated_data = data[1]
df = pd.read_csv('estimated.csv', names=('x','y'))
df['rolling_max'] = pd.rolling_max(df['y'],8500)
plt.figure()
plt.plot(actual_data[:,0],actual_data[:,1], label='actual')
plt.plot(estimated_data[:,0],estimated_data[:,1], label='estimated')
plt.plot(df['x'], df['rolling_max'], label = 'rolling')

plt.legend()
plt.title('Actual vs. Interpolated')
plt.xlim(0,10)
plt.ylim(0,500)
plt.xlabel('Time [Seconds]')
plt.ylabel('Segments')
plt.grid()
plt.show(block=True)

enter image description here

从评论中回答问题:

由于pd.rolling()正在生成数据的定义窗口,因此第一个值将是pd.rolling().maxNaN。为了替换这些NaN,我建议将整个系列转过来并向后计算窗口。然后,我们可以用向后计算的值替换所有的NaN。我调整了窗户的长度以便向后计算。否则我们会得到错误的数据。

此代码有效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
plt.ion()

df = pd.read_csv('estimated.csv', names=('x','y'))
df['rolling_max'] = df['y'].rolling(8500).max()
df['rolling_max_backwards'] = df['y'][::-1].rolling(850).max()
df.rolling_max.fillna(df.rolling_max_backwards, inplace=True)
plt.figure()
plt.plot(df['x'], df['rolling_max'], label = 'rolling')

plt.legend()
plt.title('Actual vs. Interpolated')
plt.xlim(0,10)
plt.ylim(0,700)
plt.xlabel('Time [Seconds]')
plt.ylabel('Segments')
plt.grid()
plt.show(block=True)

我们得到以下结果:

氧化镁