Wykres współrzędnych równoległych w Matplotlib

Dane dwu - i trójwymiarowe mogą być oglądane stosunkowo prosto za pomocą tradycyjnych typów wykresów. Nawet w przypadku danych czterowymiarowych często możemy znaleźć sposób na ich wyświetlenie. Wymiary powyżej czterech stają się jednak coraz trudniejsze do wyświetlenia. Na szczęście równoległe wykresy współrzędnych zapewniają mechanizm wyświetlania wyników o wyższych wymiarach.

Przykładowy wykres współrzędnych równoległych z Wikipedii

Kilka pakietów kreślarskich zapewnia równoległe wykresy współrzędnych, takie jak Matlab , R, VTK type 1 i VTK type 2 , ale nie widzę, jak utworzyć go za pomocą Matplotlib.

  1. czy w Matplotlib jest wbudowany Wykres współrzędnych równoległych? Na pewno nie widzę żadnego w galerii.
  2. jeśli nie ma wbudowanego typu, czy możliwe jest zbudowanie równoległego wykresu współrzędnych przy użyciu standardowych funkcji Matplotlib?

Edit :

Na podstawie odpowiedzi udzielonej przez Zhenya poniżej, opracowałem następujące uogólnienie, które obsługuje dowolną liczbę osi. Podążając za stylem wykresu z przykładu, który napisałem w oryginalnym pytaniu powyżej, każda oś otrzymuje swoją własną skalę. Udało mi się to dzięki normalizacji danych w każdym punkcie osi i dzięki temu osie mają zakres od 0 do 1. Następnie wracam i nakładam etykiety na każdy znak kleszcza, który daje prawidłową wartość w tym przechwyceniu.

Funkcja działa poprzez akceptację iterowalnych zbiorów danych. Każdy zbiór danych jest uważany za zbiór punkty, w których każdy punkt leży na innej osi. Przykład w __main__ chwyta losowe liczby dla każdej osi w dwóch zestawach po 30 linii. Linie są losowe w zakresach, które powodują grupowanie linii; zachowanie chciałem zweryfikować.

To rozwiązanie nie jest tak dobre jak wbudowane rozwiązanie, ponieważ masz dziwne zachowanie myszy i udaję zakresy danych przez etykiety, ale dopóki Matplotlib nie doda wbudowanego rozwiązania, jest to dopuszczalne.

#!/usr/bin/python
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

def parallel_coordinates(data_sets, style=None):

    dims = len(data_sets[0])
    x    = range(dims)
    fig, axes = plt.subplots(1, dims-1, sharey=False)

    if style is None:
        style = ['r-']*len(data_sets)

    # Calculate the limits on the data
    min_max_range = list()
    for m in zip(*data_sets):
        mn = min(m)
        mx = max(m)
        if mn == mx:
            mn -= 0.5
            mx = mn + 1.
        r  = float(mx - mn)
        min_max_range.append((mn, mx, r))

    # Normalize the data sets
    norm_data_sets = list()
    for ds in data_sets:
        nds = [(value - min_max_range[dimension][0]) / 
                min_max_range[dimension][2] 
                for dimension,value in enumerate(ds)]
        norm_data_sets.append(nds)
    data_sets = norm_data_sets

    # Plot the datasets on all the subplots
    for i, ax in enumerate(axes):
        for dsi, d in enumerate(data_sets):
            ax.plot(x, d, style[dsi])
        ax.set_xlim([x[i], x[i+1]])

    # Set the x axis ticks 
    for dimension, (axx,xx) in enumerate(zip(axes, x[:-1])):
        axx.xaxis.set_major_locator(ticker.FixedLocator([xx]))
        ticks = len(axx.get_yticklabels())
        labels = list()
        step = min_max_range[dimension][2] / (ticks - 1)
        mn   = min_max_range[dimension][0]
        for i in xrange(ticks):
            v = mn + i*step
            labels.append('%4.2f' % v)
        axx.set_yticklabels(labels)


    # Move the final axis' ticks to the right-hand side
    axx = plt.twinx(axes[-1])
    dimension += 1
    axx.xaxis.set_major_locator(ticker.FixedLocator([x[-2], x[-1]]))
    ticks = len(axx.get_yticklabels())
    step = min_max_range[dimension][2] / (ticks - 1)
    mn   = min_max_range[dimension][0]
    labels = ['%4.2f' % (mn + i*step) for i in xrange(ticks)]
    axx.set_yticklabels(labels)

    # Stack the subplots 
    plt.subplots_adjust(wspace=0)

    return plt


if __name__ == '__main__':
    import random
    base  = [0,   0,  5,   5,  0]
    scale = [1.5, 2., 1.0, 2., 2.]
    data = [[base[x] + random.uniform(0., 1.)*scale[x]
            for x in xrange(5)] for y in xrange(30)]
    colors = ['r'] * 30

    base  = [3,   6,  0,   1,  3]
    scale = [1.5, 2., 2.5, 2., 2.]
    data.extend([[base[x] + random.uniform(0., 1.)*scale[x]
                 for x in xrange(5)] for y in xrange(30)])
    colors.extend(['b'] * 30)

    parallel_coordinates(data, style=colors).show()

Edytuj 2:

Oto przykład tego, co wychodzi z powyższego kodu podczas wykreślania danych Iris Fishera . Nie jest tak ładny, jak obraz odniesienia z Wikipedii, ale jest Przejezdny, jeśli masz tylko Matplotlib i potrzebujesz wielowymiarowych Wykresów.

Przykładowy wynik wykresu współrzędnych równoległych z tej odpowiedzi

Author: Community, 2011-11-22

4 answers

Jestem pewien, że jest lepszy sposób na zrobienie tego, ale tutaj jest szybki i brudny (naprawdę brudny):

#!/usr/bin/python
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

#vectors to plot: 4D for this example
y1=[1,2.3,8.0,2.5]
y2=[1.5,1.7,2.2,2.9]

x=[1,2,3,8] # spines

fig,(ax,ax2,ax3) = plt.subplots(1, 3, sharey=False)

# plot the same on all the subplots
ax.plot(x,y1,'r-', x,y2,'b-')
ax2.plot(x,y1,'r-', x,y2,'b-')
ax3.plot(x,y1,'r-', x,y2,'b-')

# now zoom in each of the subplots 
ax.set_xlim([ x[0],x[1]])
ax2.set_xlim([ x[1],x[2]])
ax3.set_xlim([ x[2],x[3]])

# set the x axis ticks 
for axx,xx in zip([ax,ax2,ax3],x[:-1]):
  axx.xaxis.set_major_locator(ticker.FixedLocator([xx]))
ax3.xaxis.set_major_locator(ticker.FixedLocator([x[-2],x[-1]]))  # the last one

# EDIT: add the labels to the rightmost spine
for tick in ax3.yaxis.get_major_ticks():
  tick.label2On=True

# stack the subplots together
plt.subplots_adjust(wspace=0)

plt.show()

Jest to zasadniczo oparte na (o wiele ładniejszym) jednym Joe Kingon, Python / Matplotlib-czy jest sposób, aby oś nieciągła?. Możesz również rzucić okiem na inną odpowiedź na to samo pytanie.

W tym przykładzie nawet nie próbuję skalować skal pionowych, ponieważ zależy to od tego, co dokładnie próbujesz osiągnąć.

EDIT: oto wynik Tutaj wpisz opis obrazka

 13
Author: ev-br,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:10

Pandy mają równoległe współrzędne:

import pandas
import matplotlib.pyplot as plt
from pandas.tools.plotting import parallel_coordinates

data = pandas.read_csv(r'C:\Python27\Lib\site-packages\pandas\tests\data\iris.csv', sep=',')
parallel_coordinates(data, 'Name')
plt.show()

zrzut ekranu

Kod źródłowy, jak go zrobili: . py#L494

 39
Author: theta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-03 23:39:36

Uwaga: Podczas używania pand (jak sugeruje theta), nie ma możliwości samodzielnego skalowania osi.

Powodem, dla którego nie możesz znaleźć różnych osi pionowych, jest to, że ich nie ma. Nasze współrzędne równoległe "udają" dwie pozostałe osie, rysując tylko pionową linię I kilka etykiet.

Https://github.com/pydata/pandas/issues/7083#issuecomment-74253671

Sorry, nie mogę dodać tego jako bezpośredni komentarz (reputacja

 10
Author: Timmm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-31 13:25:53

Najlepszy przykład jaki do tej pory widziałem to ten

Https://python.g-node.org/python-summerschool-2013/_media/wiki/datavis/olympics_vis.py

Patrz funkcja normalized_coordinates. Nie super szybko, ale działa z tego, co próbowałem.

normalised_coordinates(['VAL_1', 'VAL_2', 'VAL_3'], np.array([[1230.23, 1500000, 12453.03], [930.23, 140000, 12453.03], [130.23, 120000, 1243.03]]), [1, 2, 1])
 0
Author: Eamonn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-12 08:01:14