2017-02-08 2 views
3

У меня есть список Numpy массивов, каждый из потенциально имеющего различного числа элементов, такие как:прокладочных листов с различным количеством элементов в Matplotlib

[array([55]), 
array([54]), 
array([], dtype=float64), 
array([48, 55]),] 

Я хотел бы построить это, где каждый массив имеет назначается абсцисса (значение x), такая как [1,2,3,4], так что на графике должны отображаться следующие пункты: [[1,55], [2, 54], [4, 48], [4, 55]]. Есть ли способ, который я могу сделать с помощью matplotlib? или как я могу преобразовать данные с numpy или pandas первым, чтобы можно было построить график?

ответ

4

Что вы хотите сделать, это связать исходный массив и создать новый массив с абсциссами. Существует много способов конкатенировать, один из наиболее эффективных - itertools.chain.

import itertools 
from numpy import array 

x = [array([55]), array([54]), array([]), array([48, 55])] 

ys = list(itertools.chain(*x)) 
# this will be [55, 54, 48, 55] 

# generate abscissas 
xs = list(itertools.chain(*[[i+1]*len(x1) for i, x1 in enumerate(x)])) 

Теперь вы можете легко построить с Matplotlib ниже

import matplotlib.pyplot as plt 
plt.plot(xs, ys) 
+0

Не совсем. Мне нужны последние два элемента: 48 и 55, которые должны быть связаны с одной и той же абсиссой (тот же x) в этом случае. 4. –

+0

Если вы хотите создать отдельную строку, я изменил код выше. Не совсем уверен, что вы пытаетесь построить, но выше будет –

+2

Это работает, но для получения 'xs = [1, 2, 4, 4]' в соответствии с запросом вам нужно использовать '[[i + 1] * len (x1) для i, x1 в перечислении (x)] '. (в настоящее время он дает '[0, 1, 3, 3]') – tom

0

с x список:

[plt.plot(np.repeat(i,len(x[i])), x[i],'.') for i in range(len(x))] 
plt.show() 
+0

Плохая практика для вызова списка 'list' – tom

+0

вы правы, это было просто ради примера :) –

+0

Спасибо, но мой фактический список очень велик, и я не думаю, что будет эффективно вызывать 'plot' столько раз. –

0

ответ @Alessandro Mariani, основанный на itertools заставил меня думать о другом пути сгенерируйте массив, содержащий данные, которые мне нужны. В некоторых случаях это может быть более компактным. Он также основан на itertools.chain:

import itertools 
from numpy import array 

y = [array([55]), array([54]), array([]), array([48, 55])] 
x = array([1,2,3,4]) 
d = array(list(itertools.chain(*[itertools.product([t], n) for t, n in zip(x,y)]))) 

d теперь следующий массив:

array([[ 1, 55], 
     [ 2, 54], 
     [ 4, 48], 
     [ 4, 55]]) 
1

Если вы хотите иметь различные маркеры для различных групп данных (цвета автоматически циклическое по matplotlib):

import numpy as np 
import matplotlib.pyplot as plt 

markers = ['o', #'circle', 
      'v', #'triangle_down', 
      '^', #'triangle_up', 
      '<', #'triangle_left', 
      '>', #'triangle_right', 
      '1', #'tri_down', 
      '2', #'tri_up', 
      '3', #'tri_left', 
      '4', #'tri_right', 
      '8', #'octagon', 
      's', #'square', 
      'p', #'pentagon', 
      'h', #'hexagon1', 
      'H', #'hexagon2', 
      'D', #'diamond', 
      'd', #'thin_diamond' 
      ] 

n_markers = len(markers) 

a = [10.*np.random.random(int(np.random.random()*10)) for i in xrange(n_markers)] 

fig = plt.figure() 
ax = fig.add_subplot(111) 
for i, data in enumerate(a): 
    xs = data.shape[0]*[i,] # makes the abscissas list 
    marker = markers[i % n_markers] # picks a valid marker 
    ax.plot(xs, data, marker, label='data %d, %s'%(i, marker)) 

ax.set_xlim(-1, 1.4*len(a)) 
ax.set_ylim(0, 10) 
ax.legend(loc=None) 
fig.tight_layout() 

Graph with different markers Обратите внимание на пределы y, жестко закодированы, соответственно изменяются. 1.4*len(a) предназначен для того, чтобы оставлять место в правой части графика для легенды.

В приведенном выше примере не имеет никакого смысла в x=0 (будет темно-синие кружки) как рандомизированы размер для его набора данных равен нулю, но вы можете легко поместить +1, если вы не хотите использовать x=0.

1

Использование панд, чтобы создать Numpy массив с NaNs вставленных когда массив пуст или короче, чем самый длинный массив в списке ...

import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt 

arr_list = [np.array([55]), 
      np.array([54]), 
      np.array([], dtype='float64'), 
      np.array([48, 55]),] 

df = pd.DataFrame(arr_list) 
list_len = len(df) 
repeats = len(list(df)) 
vals = df.values.flatten() 
xax = np.repeat(np.arange(list_len) + 1, repeats) 
df_plot = pd.DataFrame({'xax': xax, 'vals': vals}) 
plt.scatter(df_plot.xax, df_plot.vals);