【问题标题】:Creating a 2D array from Nested Dictionaries从嵌套字典创建二维数组
【发布时间】:2016-12-10 19:28:45
【问题描述】:

我是第一次使用 python 字典的学生,我一直坚持将它们用于矩阵数组。

我有一个按周描述温度和湿度的嵌套有序字典。

weather = OrderedDict([(92, OrderedDict([('Mon', 79), ('Tues', 85), 
          ('Weds', 87), ('Thurs', 83)])), 
          (96, OrderedDict([('Mon', 65), ('Tues', 71), 
          ('Weds', 74), ('Thurs', 68)])), 
          (91, OrderedDict([('Mon', 83), ('Tues', 84), 
          ('Weds', 82), ('Thurs', 80)]))])

每周的整体键表示平均湿度,每天的单独值表示温度。

我正在尝试在 matplotlib 中创建一个温度与天数线的单一图形图,它将使用湿度作为第三个变量来指示颜色条的颜色。似乎LineCollection 将使用包含日期和温度的二维数组来执行此操作。但是当我尝试从嵌套字典中拉出二维数组时,我似乎无法将它变成LineCollection 所需的 Nx2 形状。

非常感谢任何帮助!

这是我目前的代码:

plt.figure()
x=[]
y=[]
z=[]
ticks=[]
for humidity, data_dict in weather.iteritems():
    x.append(range(len(data_dict)))
    y.append(data_dict.values())
    z.append(humidity)
    ticks.append(data_dict.keys())
for ii in x,y,z:
    ii = np.array(ii)
lines=np.array(zip(x,y))
print lines.shape

这会返回形状是 (3, 2, 4) 而不是 (3, 2)

编辑: 我希望输出中的行看起来像这样,因此 numpy 可以将其识别为 3x2 2D 数组:

 [[(0 1 2 3), (79 85 87 83)],
  [(0 1 2 3), (65 71 74 68)],
  [(0 1 2 3), (83 84 82 80)]]

【问题讨论】:

  • 你想要的可变行输出是什么?
  • @Prasanna,我在问题中添加了我想要的输出。

标签: python arrays dictionary multidimensional-array matplotlib


【解决方案1】:

如果只是你想要的情节,这可能会有所帮助

from collections import OrderedDict 
import matplotlib.pyplot as plt

weather = OrderedDict([(40, OrderedDict([('Mon', 79), ('Tues', 85), 
      ('Weds', 87), ('Thurs', 83)])), 
      (90, OrderedDict([('Mon', 65), ('Tues', 71), 
      ('Weds', 74), ('Thurs', 68)])), 
      (99, OrderedDict([('Mon', 83), ('Tues', 84), 
      ('Weds', 82), ('Thurs', 80)]))])

humidity = []
temp = []
days = []

for humid,daytempdict in weather.iteritems():
    humidity.append(humid)
    days.append(range(len(daytempdict)))
    temp.append(daytempdict.values())

for (t,d,i) in zip(temp,days,humidity):   
    #normalize humidity by max humidity
    c = float(i)/max(humidity)
    #color according to the normalized humidity, shade of red
    c = tuple((1*  c ,0,0))   
    plt.plot(d,t,color=c,label="humidity "+str(i) )

plt.xlabel("days")
plt.ylabel("tempreture")
plt.legend(loc="best")
plt.show()          

【讨论】:

  • 非常感谢!您能解释一下为什么需要对颜色进行归一化吗?
  • 湿度在 90s 范围内,我们使用的颜色 rgb 元组允许值在 0-1 范围内。如果我们将湿度值除以最大湿度,我们将始终获得小于或等于 1 的值。
【解决方案2】:

您需要遍历将值附加到列表的嵌套字典。您还应该存储天数,以便有一些东西可以绘制温度。湿度的颜色也应该每天储存。然后,您需要定义轴标签以将日期显示为字符串。执行此操作的代码如下所示,

from collections import OrderedDict
import matplotlib.pyplot as plt

weather = OrderedDict([(92, OrderedDict([('Mon', 79), 
                                         ('Tues', 85), 
                                         ('Weds', 87), 
                                         ('Thurs', 83)])), 
                       (96, OrderedDict([('Mon', 65), 
                                         ('Tues', 71), 
                                         ('Weds', 74), 
                                         ('Thurs', 68)])), 
                       (91, OrderedDict([('Mon', 83), 
                                         ('Tues', 84), 
                                         ('Weds', 82), 
                                         ('Thurs', 80)]))])
Temp = []
Humidity = []
Day = []
Dayno = []
for h, v in weather.items():
    j = 0
    for d, T in v.items():
        Temp.append([T])
        Humidity.append([h])
        Day.append([d])
        Dayno.append([j])
        j += 1

fig,ax = plt.subplots(1,1)
cm = ax.scatter(Dayno, Temp, c=Humidity, 
                vmin=90., vmax=100., 
                cmap=plt.cm.RdYlBu_r)
ax.set_xticks(Dayno[0:4])
ax.set_xticklabels(Day[0:4])
plt.colorbar(cm)
plt.show()

哪些情节,

更新:如果要使用绘图,则需要将数据分成每周的数组,然后将它们绘制为单行。然后,您可以为每条线和标签设置颜色。我附加了一个使用 numpy 和数组切片的版本(虽然可能不是最简单的解决方案),

from collections import OrderedDict
import matplotlib.pyplot as plt
import matplotlib
import numpy as np

weather = OrderedDict([(92, OrderedDict([('Mon', 79), 
                                         ('Tues', 85), 
                                         ('Weds', 87), 
                                         ('Thurs', 83)])), 
                       (96, OrderedDict([('Mon', 65), 
                                         ('Tues', 71), 
                                         ('Weds', 74), 
                                         ('Thurs', 68)])), 
                       (91, OrderedDict([('Mon', 83), 
                                         ('Tues', 84), 
                                         ('Weds', 82), 
                                         ('Thurs', 80)]))])
Temp = []; Humidity = []
Day = []; Dayno = []; weekno = []
i = 0
for h, v in weather.items():
    j = 0
    for d, T in v.items():
        Temp.append(T)
        Humidity.append(h)
        Day.append(d)
        Dayno.append(j)
        weekno.append(i)
        j += 1
    i += 1

#Swtich to numpy arrays to allow array slicing
Temp = np.array(Temp)
Humidity = np.array(Humidity)
Day = np.array(Day)
Dayno = np.array(Dayno)
weekno = np.array(weekno)

#Plot lines
fig,ax = plt.subplots(1,1)
vmin=90.; vmax=97.; 
weeks=3; daysperweek=4
colour = ['r', 'g', 'b']
for i in range(weeks):
    ax.plot(Dayno[weekno==i], 
            Temp[weekno==i], 
            c=colour[i], 
            label="Humidity = " + str(Humidity[daysperweek*i]))

ax.set_xticks(Dayno[0:4])
ax.set_xticklabels(Day[0:4])
plt.legend(loc="best")
plt.show()

看起来像,

【讨论】:

  • 我本来想这样做,但我需要我的情节是一个线图。我可以弄清楚如何将第三个变量与线图一起使用的唯一方法是使用 LineCollection,但任何解决方案都是有用的!
  • 非常感谢!
【解决方案3】:

如果你想要一个二维数组,你需要将你的范围与 x 和 y 连接起来,而不是追加。你没有得到你想要的输出的原因是 x.append(list) 将列表作为 x 的一个元素插入——这意味着你有

[[0, 1, 2, 3], [0, 1, 2, 3],...] 

当你想要的时候

[0,1,2,3,0,...]

像这样修改你的 for 循环应该会产生一个 (12, 2) 天数和温度数组:

for humidity, data_dict in weather.iteritems():
    x = x + range(len(data_dict))
    y = y + (data_dict.values())

【讨论】:

    猜你喜欢
    • 2015-12-22
    • 2021-09-14
    • 2019-02-25
    • 2018-03-31
    • 2021-12-08
    • 1970-01-01
    • 2021-08-14
    • 2021-04-04
    相关资源
    最近更新 更多