【问题标题】:Plot a list of differently named tuples over time随着时间的推移绘制一个不同命名的元组列表
【发布时间】:2020-10-25 05:34:50
【问题描述】:

数据如下所示,其中每个键: datetime 都有一个带有字母和相应百分比的元组列表。我正在尝试制作类似于下图的内容,但是我在处理这些字母时遇到了一些问题,因为它们在字母来来去去的整个过程中并不一致,就像示例中那样。

{
 datetime.datetime(2020, 2, 14, 0, 0): 
  [('A', 0.1),
  ('B', 0.2),
  ('C', 0.1),
  ('D', 0.25),
  ('E', 0.05)],
 datetime.datetime(2020, 5, 15, 0, 0): 
  [('A', 0.1),
  ('B', 0.14),
  ('C', 0.09),
  ('D', 0.16),
  ('F', 0.6)],   # Note F
  ...
}

【问题讨论】:

  • 难道你还不能通过指定不同的xs...来绘制各种系列吗? plot(x, y)

标签: python dictionary datetime matplotlib plot


【解决方案1】:

这是一个根据内部键展开字典的问题,与绘图相关的键

from matplotlib.pyplot import plot, show
from datetime import datetime as dt

data = {dt(2020,2,14,0,0):[('A',0.1),('B',0.20),('C',0.10),('D',0.25),('E',0.05)],
        dt(2020,5,15,0,0):[('A',0.1),('B',0.14),('C',0.09),('D',0.16),('F',0.60)]}
by_inner_key = {}
for date, tuples in data.items():
    for k, val in tuples: by_inner_key.setdefault(k, []).append((date, val))
for k in by_inner_key: plot(*zip(*by_inner_key[k])
show()

给出(注意与'F'相关的异常值)


现在是一个带有内联 cmets 和一些当之无愧的装饰的版本

from matplotlib.pyplot import legend, plot, show, xticks
from datetime import datetime as dt

data = {dt(2020,2,14,0,0):[('A',0.1),('B',0.20),('C',0.10),('D',0.25),('E',0.05)],
        dt(2020,5,15,0,0):[('A',0.1),('B',0.14),('C',0.09),('D',0.16),('F',0.60)]}

# unfold `data` using the first tuple element as the key,
# storing dates and values in a list of 2-tuples
# {'A':[(date0,value0),(date1,value1),...], 'B':[...], ...}

by_inner_key = {}
for date, tuples in data.items():
    for key, value in tuples:
        by_inner_key.setdefault(key, []).append((date, value))

# plot the data ordered by key
# for the sake of clarity we unpack the transposed list
for key, list_of_tuples in by_inner_key.items():
    # OP's data is already sorted but who knows…
    list_of_tuples.sort()
    dates, values = zip(*list_of_tuples) # transpose, from N 2-tuples to 2 N-tuples
    plot(dates, values, label=key)
#cosmetics    
xticks((dt(2020,2,14),dt(2020,3,15),dt(2020,4,15),dt(2020,5,15)))
legend(ncol=6)
show()

更好,不是吗?

如果您不想显示未绘制线条的图例,您可以执行以下操作

    plot(dates, values, label=key if len(values)>1 else '')

【讨论】:

    【解决方案2】:

    检查此代码:

    import pandas as pd
    import datetime
    import matplotlib.pyplot as plt
    import seaborn as sns
    
    data = {
        datetime.datetime(2020, 2, 14, 0, 0):
            [('A', 0.1),
             ('B', 0.2),
             ('C', 0.1),
             ('D', 0.25),
             ('E', 0.05)],
        datetime.datetime(2020, 2, 15, 0, 0):
            [('A', 0.1),
             ('B', 0.14),
             ('C', 0.09),
             ('D', 0.16),
             ('F', 0.6)],
        datetime.datetime(2020, 2, 16, 0, 0):
            [('A', 0.1),
             ('C', 0.25),
             ('D', 0.05),
             ('E', 0.3),
             ('F', 0.15)],
        datetime.datetime(2020, 2, 17, 0, 0):
            [('B', 0.15),
             ('C', 0.25),
             ('D', 0.2),
             ('E', 0.25),
             ('F', 0.05)],
        datetime.datetime(2020, 2, 18, 0, 0):
            [('A', 0.2),
             ('B', 0.3),
             ('C', 0.1),
             ('D', 0.15),
             ('E', 0.25)],
        datetime.datetime(2020, 2, 19, 0, 0):
            [('A', 0.15),
             ('B', 0.15),
             ('C', 0.1),
             ('E', 0.3),
             ('F', 0.25)],
        datetime.datetime(2020, 2, 20, 0, 0):
            [('A', 0.15),
             ('B', 0.25),
             ('C', 0.05),
             ('D', 0.1),
             ('E', 0.35)],
    }
    
    df = pd.DataFrame(columns = ['date', 'letter', 'value'])
    
    for key, value in data.items():
        date = pd.DataFrame({'date': [key]*len([couple[0] for couple in value]),
                             'letter': [couple[0] for couple in value],
                             'value': [couple[1] for couple in value]})
        df = df.append(date)
    
    
    fig, ax = plt.subplots(figsize = (12, 6))
    
    sns.lineplot(ax = ax,
                 data = df,
                 x = 'date',
                 y = 'value',
                 hue = 'letter')
    
    plt.show()
    

    为了制作情节,我生成了一些与您类似的数据。
    然后我将数据按日期组织在一个临时数据框date 中,以便从列表中提取字母和值。然后我将这个临时数据框附加到一般的 df 看起来像:

            date letter  value
    0 2020-02-14      A   0.10
    1 2020-02-14      B   0.20
    2 2020-02-14      C   0.10
    3 2020-02-14      D   0.25
    4 2020-02-14      E   0.05
    0 2020-02-15      A   0.10
    1 2020-02-15      B   0.14
    2 2020-02-15      C   0.09
    3 2020-02-15      D   0.16
    4 2020-02-15      F   0.60
    0 2020-02-16      A   0.10
    1 2020-02-16      C   0.25
    2 2020-02-16      D   0.05
    3 2020-02-16      E   0.30
    4 2020-02-16      F   0.15
    0 2020-02-17      B   0.15
    1 2020-02-17      C   0.25
    2 2020-02-17      D   0.20
    3 2020-02-17      E   0.25
    4 2020-02-17      F   0.05
    0 2020-02-18      A   0.20
    1 2020-02-18      B   0.30
    2 2020-02-18      C   0.10
    3 2020-02-18      D   0.15
    4 2020-02-18      E   0.25
    0 2020-02-19      A   0.15
    1 2020-02-19      B   0.15
    2 2020-02-19      C   0.10
    3 2020-02-19      E   0.30
    4 2020-02-19      F   0.25
    0 2020-02-20      A   0.15
    1 2020-02-20      B   0.25
    2 2020-02-20      C   0.05
    3 2020-02-20      D   0.10
    4 2020-02-20      E   0.35
    

    最后,我按日期绘制值,并根据 sns.lineplot 的字母进行拆分。我明白了这个情节。

    如您所见,2020-02-14 上的字母 F 没有出现在数据中以及图中。在2020-02-15 上,字母E 没有出现在数据中,因此在图中,线会跳过这个日期,E 的下一个值在2020-02-16 上。

    【讨论】:

    • 太棒了,正是我想要的!不知道你可以绘制那种类型的数据框。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多