3

Я студент, впервые работающий с словарями python, и я зацикливаюсь на их применении в матричных массивах.Создание 2D-массива из вложенных словарей

У меня есть вложенный упорядоченный словарь, описывающий температуру и влажность неделю за неделей.

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 сделает это с помощью 2D-массива дня и температуры. Но когда я пытаюсь вытащить 2D-массив из вложенного словаря, я не могу представить его в нужной форме Nx2 для LineCollection.

Любая помощь очень ценится!

Вот код, который я до сих пор:

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)

EDIT: Я надеясь на линию в выходе, который выглядит, как это, так 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)]] 
+0

Что вы желаемый результат для переменных строк? – Prasanna

+0

@Прасанна, я добавил свой желаемый результат на вопрос. – morepenguins

ответ

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() 

которых участки,

enter image description here

UPDATE: Если вы хотите использовать участки, которые необходимо разделить данные в массив для каждой недели, а затем постройте их как одну строку. Затем вы можете установить цвет для каждой строки и метки.Я приложил версию с помощью 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() 

Который выглядит, enter image description here

+0

Я хотел сделать это изначально, но мне нужно, чтобы мой сюжет был линейным сюжетом. Единственный способ понять, как использовать третью переменную с линейным строком, был с LineCollection, но любое решение для этого полезно! – morepenguins

+0

Большое вам спасибо! – morepenguins

0

Если вы хотите 2D массива, который вы должны быть конкатенациями ваших диапазонов с й и у, а не appendi нг. Причина вы не получаете вывод, который вы хотите это x.append (список) вставляет список как элемент х - это означает, что у вас есть

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

, когда кажется, что вы хотите

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

модифицируя цикл как и должны произвести (12, 2) массива дней и температур:

for humidity, data_dict in weather.iteritems(): 
    x = x + range(len(data_dict)) 
    y = y + (data_dict.values()) 
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()   

The plot looks like this

+0

Большое вам спасибо! Не могли бы вы объяснить, почему цвет необходимо нормализовать? – morepenguins

+0

влажность находится в диапазоне 90 с, а используемый нами цветовой код rgb допускает значения в диапазоне 0-1. Если мы разделим значения влажности на максимум влажности, мы всегда получим значение, меньшее или равное 1. – Prasanna

Смежные вопросы