создание диаграмм рассеяния matplotlib из фреймов данных в панд Python



каков наилучший способ сделать серию диаграмм рассеяния с помощью matplotlib С pandas фрейм данных в Python?



например, если у меня есть фрейм данных df что имеет некоторые столбцы интереса, я нахожу себя обычно преобразования все в массивы:



import matplotlib.pylab as plt
# df is a DataFrame: fetch col1 and col2
# and drop na rows if any of the columns are NA
mydata = df[["col1", "col2"]].dropna(how="any")
# Now plot with matplotlib
vals = mydata.values
plt.scatter(vals[:, 0], vals[:, 1])


проблема с преобразованием всего в массив перед построением графика заключается в том, что он заставляет вас вырваться из фреймов данных.



рассмотрим эти два варианта использования, когда имеется полный фрейм данных имеет важное значение для построения графика:





  1. например, что делать, если вы хотите теперь посмотреть на все значения col3 для соответствующих значений, которые вы построили в вызове scatter, и цвет каждой точки (или размер) это значение? Вам придется вернуться, вытащить не на значения col1,col2 и проверить, что их соответствующие значения.



    есть ли способ построить график при сохранении фрейма данных? Для пример:



    mydata = df.dropna(how="any", subset=["col1", "col2"])
    # plot a scatter of col1 by col2, with sizes according to col3
    scatter(mydata(["col1", "col2"]), s=mydata["col3"])



  2. аналогично, представьте, что вы хотите фильтровать или окрашивать каждую точку по-разному в зависимости от значений некоторых из ее столбцов. Например, что делать, если вы хотите автоматически построить метки точек, которые соответствуют определенному срезу на col1, col2 рядом с ними (где метки хранятся в другом столбце df), или цвет этих точек по-разному, как люди делают с кадрами данных в R. Для пример:



    mydata = df.dropna(how="any", subset=["col1", "col2"]) 
    myscatter = scatter(mydata[["col1", "col2"]], s=1)
    # Plot in red, with smaller size, all the points that
    # have a col2 value greater than 0.5
    myscatter.replot(mydata["col2"] > 0.5, color="red", s=0.5)



как это можно сделать?



EDIT ответить crewbum:



вы говорите, что лучший способ-построить каждое условие (например,subset_a,subset_b) отдельно. Что делать, если у вас есть много условий, например, вы хотите разделить рассеиватели на 4 типа точек или даже больше, построив каждый из них в разной форме/цвете. Как вы можете элегантно применить условие a, b, c и т. д. и убедитесь, что вы затем сюжет "остальное" (вещи ни в одном из этих условий) как последний шаг?



аналогично в вашем примере, где вы строитеcol1,col2 зависимости col3, что делать, если есть значения NA, которые нарушают связь между col1,col2,col3? Например, если вы хотите построить все col2 ценности, основанные на их col3 значения, но некоторые строки имеют значение NA в любом col1 или col3, вынуждает вас использовать dropna первый. Так что вы бы сделали:



mydata = df.dropna(how="any", subset=["col1", "col2", "col3")


тогда вы можете построить с помощью mydata как вы показать -- построение разброса между col1,col2 использовать значение col3. Но mydata будут отсутствовать некоторые пункты, которые имеют значения для col1,col2, но на col3, и те еще должны быть построены... Итак, как бы вы в основном построили "остальные" данные, т. е. точки, которые не в отфильтрованном наборе mydata?

1774   2  

2 ответов:

попробуйте передать столбцы DataFrame непосредственно в matplotlib, как в примерах ниже, вместо извлечения их в виде массивов numpy.

df = pd.DataFrame(np.random.randn(10,2), columns=['col1','col2'])
df['col3'] = np.arange(len(df))**2 * 100 + 100

In [5]: df
Out[5]: 
       col1      col2  col3
0 -1.000075 -0.759910   100
1  0.510382  0.972615   200
2  1.872067 -0.731010   500
3  0.131612  1.075142  1000
4  1.497820  0.237024  1700

варьировать размер точки рассеяния на основе другого столбца

plt.scatter(df.col1, df.col2, s=df.col3)
# OR (with pandas 0.13 and up)
df.plot(kind='scatter', x='col1', y='col2', s=df.col3)

enter image description here

изменить цвет точки рассеяния на основе другого столбца

colors = np.where(df.col3 > 300, 'r', 'k')
plt.scatter(df.col1, df.col2, s=120, c=colors)
# OR (with pandas 0.13 and up)
df.plot(kind='scatter', x='col1', y='col2', s=120, c=colors)

enter image description here

Scatter plot с легендой

тем не менее, самый простой способ, который я нашел, чтобы создать точечную диаграмму с легенда, чтобы позвонить plt.scatter один раз для каждого типа.

cond = df.col3 > 300
subset_a = df[cond].dropna()
subset_b = df[~cond].dropna()
plt.scatter(subset_a.col1, subset_a.col2, s=120, c='b', label='col3 > 300')
plt.scatter(subset_b.col1, subset_b.col2, s=60, c='r', label='col3 <= 300') 
plt.legend()

enter image description here

обновление

из того, что я могу сказать, matplotlib просто пропускает точки с координатами NA x/y или настройками стиля NA (например, цвет/размер). Чтобы найти точки, пропущенные из-за NA, попробуйте isnull способ: df[df.col3.isnull()]

чтобы разделить список точек на множество типов, взгляните на включает в себя select, который является векторизованным if-then-else реализация и принимает необязательное значение по умолчанию. Например:

df['subset'] = np.select([df.col3 < 150, df.col3 < 400, df.col3 < 600],
                         [0, 1, 2], -1)
for color, label in zip('bgrm', [0, 1, 2, -1]):
    subset = df[df.subset == label]
    plt.scatter(subset.col1, subset.col2, s=120, c=color, label=str(label))
plt.legend()

enter image description here

мало что можно добавить к великому ответу Гаррета, но у панд также есть scatter метод. Используя это, это так же просто, как

df = pd.DataFrame(np.random.randn(10,2), columns=['col1','col2'])
df['col3'] = np.arange(len(df))**2 * 100 + 100
df.plot.scatter('col1', 'col2', df['col3'])

plotting sizes in col3 to col1-col2

Comments

    Ничего не найдено.