Python线条绘制同一图上的多个时间序列

问题描述 投票:2回答:2

我正在解析一个文件,该文件按时间顺序为多个时间序列加上时间戳,我想在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)]}
python matplotlib
2个回答
3
投票

我喜欢这类问题的熊猫。

首先,将数据放在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)


2
投票

简短回答:

突出显示并按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()

然后你会得到:

enter image description here


细节

这个问题中有一些令人困惑的因素。如果您所说的源数据是以下形式:

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

在任何情况下,绝对没有理由利用字典来获取你的字典

[...]包含所有这些数据的单线图。我希望在一个情节中为系列,系列,系列等提供独立的线条。

我相信最有效的方法是来自Reshaping and Pivot Tablespandas docs。从那里你可以使用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

鉴于有些特殊的时间指数,仍有一些问题需要处理。为了使这些数据更友好,我们应该处理缺失的值。这可以在使用df.fillnapandas docs的下一个片段中轻松完成:

# 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()即可获得折线图:

enter image description here

编辑:

让我知道您的数据源是什么,以便为您提供有关如何读取和存储数据的一些提示。再说一次,熊猫很可能是最好的选择。

© www.soinside.com 2019 - 2024. All rights reserved.