створення графіків розсіювання matplotlib з фреймів даних у пандах Python


78

Який найкращий спосіб створити серію графіків розсіювання за 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 Відповісти на альбом екіпажу:

Ви кажете, що найкращий спосіб - побудувати кожну умову (наприклад 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але для яких є NA col3, і вони все ще повинні бути побудовані ... так як би ви в основному побудували "решту" даних, тобто точки, яких немає у відфільтрованому наборі mydata?


2
Речі тим часом змінюються, див. " Складання - Складання - Розсіяний сюжет" з офіційної документації.
Piotr Migdal

Відповіді:


115

Спробуйте передати стовпці 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)

введіть тут опис зображення

Змінюйте колір точки розсіювання на основі іншого стовпця

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)

введіть тут опис зображення

Розсіяний сюжет з легендою

Однак найпростіший спосіб, який я знайшов, щоб створити графік розсіювання з легендою - це зателефонувати 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()

введіть тут опис зображення

Оновлення

З того, що я можу сказати, matplotlib просто пропускає точки з координатами x / y NA або налаштуваннями стилю NA (наприклад, колір / розмір). Щоб знайти точки, пропущені через НС, спробуйте isnullметод:df[df.col3.isnull()]

Щоб розділити список точок на багато типів, погляньте на numpyselect , який є векторизованою реалізацією 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()

введіть тут опис зображення


1
чудова відповідь! Я не знав про них. Зазвичай я отримую свої дані у форматі, який мені подобається, і надсилаю їх у R для ggplot. Ці приклади дозволять мені зробити набагато більше в рамках pandas / python - дякую.
zach

Як я можу зробити одне коло з конкретним розміром у легенді?
nbsrujan

6

До чудової відповіді Гаррета мало що можна додати, але панди також мають 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'])

побудова графіків розмірів від col3 до col1-col2


3

Я порекомендую використовувати альтернативний метод, використовуючи seabornбільш потужний інструмент для побудови даних. Ви можете використовувати seaborn scatterplotта визначати стовпчик 3 як hueі size.

Робочий код:

import pandas as pd
import seaborn as sns
import numpy as np

#creating sample data 
sample_data={'col_name_1':np.random.rand(20),
      'col_name_2': np.random.rand(20),'col_name_3': np.arange(20)*100}
df= pd.DataFrame(sample_data)
sns.scatterplot(x="col_name_1", y="col_name_2", data=df, hue="col_name_3",size="col_name_3")

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.