繁体   English   中英

Python线图在同一图上的多个时间序列

[英]Python line plot multiple time series on same plot

我正在解析一个文件,该文件具有要在python中解析的多个时间序列的按时间顺序标记的数据,然后使用matplotlib为每个时间序列数据集创建具有独立线条的单线图。 我正在解析的数据如下所示:

time label   value
1.05 seriesA 3.925
1.09 seriesC 0.245
2.13 seriesB 12.32
2.73 seriesC 4.921

我已将文件解析为包含在系列标签上键控的(时间,值)元组的列表的字典。 我正在努力如何使用所有这些数据将其绘制成单线图。 我想要在单个绘图上为seriesA,seriesB,seriesC等使用独立的线。 有指针吗?

编辑:根据要求,字典在下面。 我很难弄清楚存储这些数据的最佳方法,所以也许我正在使用的数据结构也是一个问题。 下面的键是不同的时间序列标签,值是(时间,值)元组的列表。 无论如何,这里是:

{'client1': [(861.991698574, 298189000.0), (862.000768158, 0.0)], 
'client2': [(861.781502324, 0.0), (861.78903722, 153600000.0), 
(862.281483262, 0.0), (862.289038158, 153600000.0)], 'client3': 
[(862.004470762, 3295674368.0), (862.004563939, 3295674368.0), 
(862.03981821, 799014912.0), (862.040403314, 1599078400.0), 
(862.540269616, 3295674368.0), (862.55133097, 1599078400.0)]}

我喜欢这种问题的熊猫。

首先,将数据放入pandas数据框中:

import pandas as pd

data = {'client1': [(861.991698574, 298189000.0), (862.000768158, 0.0)], 
'client2': [(861.781502324, 0.0), (861.78903722, 153600000.0), 
(862.281483262, 0.0), (862.289038158, 153600000.0)], 'client3': 
[(862.004470762, 3295674368.0), (862.004563939, 3295674368.0), 
(862.03981821, 799014912.0), (862.040403314, 1599078400.0), 
(862.540269616, 3295674368.0), (862.55133097, 1599078400.0)]}

time = []
label = []
value = []

for k, v in data.items():
    for tup in v:
        label.append(k)
        time.append(tup[0])
        value.append(tup[1])

df = pd.DataFrame({'time':time, 'label':label, 'value':value})

结果如下:

>>> df
      label        time         value
0   client1  861.991699  2.981890e+08
1   client1  862.000768  0.000000e+00
2   client2  861.781502  0.000000e+00
3   client2  861.789037  1.536000e+08
4   client2  862.281483  0.000000e+00
5   client2  862.289038  1.536000e+08
6   client3  862.004471  3.295674e+09
7   client3  862.004564  3.295674e+09
8   client3  862.039818  7.990149e+08
9   client3  862.040403  1.599078e+09
10  client3  862.540270  3.295674e+09
11  client3  862.551331  1.599078e+09

然后,您可以执行以下操作:

by_label = df.groupby('label')

for name, group in by_label:
    plt.plot(group['time'], group['value'], label=name)

plt.legend()
plt.show

关于如何将数据存储在字典中; 有多种解决方法,但是如果我是你,并且能够通过pandas轻松使用您的数据,我将使用以下形式的字典:

data = {'label':['client1', 'client1', 'client2', ...], 
 'time':[time1, time2, time3, ...], 
 'value':[value1, value2, value3, ...]}

确保以正确的方式对所有列表进行排序(所有3个键的索引0为数据帧的第0行,索引1为数据行1,依此类推)。 然后要导入大熊猫,您需要做的就是df = pd.DataFrame(data)

简短答案:

突出显示并按住Ctrl键按住c键,可以看到以下数据:

label        time         value
client1  861.991699  2.981890e+08
client1  862.000768  0.000000e+00
client2  861.781502  0.000000e+00
client2  861.789037  1.536000e+08
client2  862.281483  0.000000e+00
client2  862.289038  1.536000e+08
client3  862.004471  3.295674e+09
client3  862.004564  3.295674e+09
client3  862.039818  7.990149e+08
client3  862.040403  1.599078e+09
client3  862.540270  3.295674e+09
client3  862.551331  1.599078e+09

然后运行以下代码段:

# imports
import pandas as pd

# read data from the clipboard
df = pd.read_clipboard(sep='\\s+')

# reshape the data to get values by time for each label
df = df.pivot(index='time', columns='label', values='value')

# Replace nans by forward filling existing values
df = df.fillna(method = 'ffill')

# You'll still have to handle the missing values in the beginning of the coloumns
df = df.fillna(method = 'bfill')

# A simple plot:
df.plot()

然后您将获得:

在此处输入图片说明


细节

这个问题有一些令人困惑的要素。 如您所说,如果数据的格式为:

time label   value
1.05 seriesA 3.925
1.09 seriesC 0.245
2.13 seriesB 12.32
2.73 seriesC 4.921

但是数据的真实内容是:

{'client1': [(861.991698574, 298189000.0), (862.000768158, 0.0)], 
'client2': [(861.781502324, 0.0), (861.78903722, 153600000.0), 
(862.281483262, 0.0), (862.289038158, 153600000.0)], 'client3': 
[(862.004470762, 3295674368.0), (862.004563939, 3295674368.0), 
(862.03981821, 799014912.0), (862.040403314, 1599078400.0), 
(862.540269616, 3295674368.0), (862.55133097, 1599078400.0)]}

然后,数据的真实内容和形式应为:

label        time         value
client1  861.991699  2.981890e+08
client1  862.000768  0.000000e+00
client2  861.781502  0.000000e+00
client2  861.789037  1.536000e+08
client2  862.281483  0.000000e+00
client2  862.289038  1.536000e+08
client3  862.004471  3.295674e+09
client3  862.004564  3.295674e+09
client3  862.039818  7.990149e+08
client3  862.040403  1.599078e+09
client3  862.540270  3.295674e+09
client3  862.551331  1.599078e+09

无论如何,绝对没有理由利用字典来获取您的

带有所有这些数据的单线图。 我想要在单个绘图上为seriesA,seriesB,seriesC等使用独立的线。

我认为,最有效的方法是pandas文档中的“ 重塑和数据透视表 ”。 从那里可以使用df.plot()直接绘制数据。

突出显示并按Ctrl + c上面的数据,您可以执行以下操作:

# imports
import pandas as pd

# read data from the clipboard
df = pd.read_clipboard(sep='\\s+')

# reshape the data to get values by time for each label
df = df.pivot(index='time', columns='label', values='value')
print(df)

这应该代表所需的数据形式:

label           client1      client2       client3
time                                              
861.781502          NaN          0.0           NaN
861.789037          NaN  153600000.0           NaN
861.991699  298189000.0          NaN           NaN
862.000768          0.0          NaN           NaN
862.004471          NaN          NaN  3.295674e+09
862.004564          NaN          NaN  3.295674e+09
862.039818          NaN          NaN  7.990149e+08
862.040403          NaN          NaN  1.599078e+09
862.281483          NaN          0.0           NaN
862.289038          NaN  153600000.0           NaN
862.540270          NaN          NaN  3.295674e+09
862.551331          NaN          NaN  1.599078e+09

鉴于时间索引有些特殊,仍有一些问题需要处理。 为了使该数据易于绘制,我们应该处理缺失的值。 使用pandas docs中的 df.fillna在下一个代码段中可以轻松完成此操作:

# Replace nans by forward filling existing values
df = df.fillna(method = 'ffill')

# You'll still have to handle the missing values
# in the beginning of the coloumns
df = df.fillna(method = 'bfill')

现在,您只需使用df.plot()即可获得折线图:

在此处输入图片说明

编辑:

让我知道您的数据源是什么,以便为您提供一些有关如何读取和存储数据的提示。 同样,大熊猫也是最有可能走的路。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM