Kontury Scatterplot W Matplotlib
[[0]}mam ogromny scatterplot (~100,000 punktów), który generuję w matplotlib. Każdy punkt ma miejsce w tej przestrzeni x/y i chciałbym wygenerować kontury zawierające pewne percentyle całkowitej liczby punktów.
Czy w matplotlib jest funkcja, która to zrobi? Przyjrzałem się contour (), ale musiałbym napisać własną funkcję, aby działać w ten sposób.
Dzięki!
2 answers
Zasadniczo, chcesz oszacować gęstość jakiegoś rodzaju. Można to zrobić na wiele sposobów:
Użyj histogramu 2D jakiegoś rodzaju (np.
matplotlib.pyplot.hist2d
lubmatplotlib.pyplot.hexbin
) (Możesz również wyświetlić wyniki jako kontury-po prostu użyjnumpy.histogram2d
, a następnie kontur tablicy wynikowej.)Wykonaj oszacowanie gęstości jądra (KDE) i konturuj wyniki. KDE jest zasadniczo wygładzonym histogramem. Zamiast punktu wpadającego do określonego pojemnika, dodaje wagę do otaczających pojemników (zwykle w kształcie Gaussa "krzywa dzwonka").
Korzystanie z histogramu 2D jest proste i łatwe do zrozumienia, ale funddemently daje "blokowe" wyniki.
Są pewne zmarszczki do zrobienia drugiego "poprawnie" (tzn. nie ma jednego poprawnego sposobu). Nie będę tu wchodzić w szczegóły, ale jeśli chcesz statystycznie zinterpretować wyniki, musisz poczytać o tym (szczególnie o wyborze pasma).
W każdym razie, oto przykład różnic. I ' m każdy z nich będzie rysowany podobnie, więc nie będę używał konturów, ale równie łatwo można narysować histogram 2D lub Gaussian KDE za pomocą wykresu konturów:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import kde
np.random.seed(1977)
# Generate 200 correlated x,y points
data = np.random.multivariate_normal([0, 0], [[1, 0.5], [0.5, 3]], 200)
x, y = data.T
nbins = 20
fig, axes = plt.subplots(ncols=2, nrows=2, sharex=True, sharey=True)
axes[0, 0].set_title('Scatterplot')
axes[0, 0].plot(x, y, 'ko')
axes[0, 1].set_title('Hexbin plot')
axes[0, 1].hexbin(x, y, gridsize=nbins)
axes[1, 0].set_title('2D Histogram')
axes[1, 0].hist2d(x, y, bins=nbins)
# Evaluate a gaussian kde on a regular grid of nbins x nbins over data extents
k = kde.gaussian_kde(data.T)
xi, yi = np.mgrid[x.min():x.max():nbins*1j, y.min():y.max():nbins*1j]
zi = k(np.vstack([xi.flatten(), yi.flatten()]))
axes[1, 1].set_title('Gaussian KDE')
axes[1, 1].pcolormesh(xi, yi, zi.reshape(xi.shape))
fig.tight_layout()
plt.show()
Jedno zastrzeżenie: przy bardzo dużej liczbie punktów, scipy.stats.gaussian_kde
będzie bardzo wolno. Jest to dość łatwe do przyspieszenia poprzez przybliżenie--wystarczy wziąć histogram 2D i rozmyć go z guassian filtrem odpowiedniego promienia i kowariancji. Mogę podać przykład, jeśli chcesz.
Jeszcze jedno zastrzeżenie: jeśli jesteś robiąc to w nie-kartezjańskim układzie współrzędnych, żadna z tych metod nie ma zastosowania ! Uzyskanie oszacowania gęstości na kulistej skorupie jest nieco bardziej skomplikowane.
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-10-15 21:16:53
Mam to samo pytanie. Jeśli chcesz rysować kontury, które zawierają pewną część punktów, możesz użyć następującego algorytmu:
Tworzenie histogramu 2d
h2, xedges, yedges = np.histogram2d(X, Y, bibs = [30, 30])
H2 jest teraz macierzą 2d zawierającą liczby całkowite, która jest liczbą punktów w pewnym prostokącie
hravel = np.sort(np.ravel(h2))[-1] #all possible cases for rectangles
hcumsum = np.sumsum(hravel)
Brzydki hack,
Dajmy dla każdego punktu w macierzy H2 2D skumulowaną liczbę punktów dla prostokąta, które zawierają liczbę punktów równą lub większą do tej, którą analizujemy obecnie.
hunique = np.unique(hravel)
hsum = np.sum(h2)
for h in hunique:
h2[h2 == h] = hcumsum[np.argwhere(hravel == h)[-1]]/hsum
Teraz fabuła kontur dla h2, będzie to kontur zawierający pewną ilość wszystkich punktów
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
2015-01-28 10:01:39