2013-10-11 11 views
6

Ich erzeuge ein Streudiagramm von ~ 300k Datenpunkten und habe das Problem, dass es an manchen Stellen so überfüllt ist, dass keine Struktur sichtbar ist - also hatte ich einen Gedanken !Plot Konturen für den dichtesten Bereich eines Streudiagramms

Ich möchte, dass das Plot ein Konturdiagramm für die dichtesten Teile erzeugt und die weniger dichten Bereiche mit den scatter() Datenpunkten belässt.

Also habe ich versucht, für jeden der Datenpunkte einen nächsten Nachbarabstand einzeln zu berechnen und dann, wenn dieser Abstand einen bestimmten Wert erreicht, eine Kontur zeichnen und füllen, dann wenn es einen viel größeren Wert trifft (weniger dicht) tun Sie einfach die Streuung ...

Ich habe versucht und versagt seit ein paar Tagen, ich bin mir nicht sicher, dass das konventionelle Konturdiagramm in diesem Fall funktioniert.

Ich würde Code zur Verfügung stellen, aber es ist so chaotisch und würde wahrscheinlich nur das Problem verwirren. Und es ist so rechenintensiv, dass es wahrscheinlich nur meinen PC zum Absturz bringen würde, wenn es funktionieren würde!

Vielen Dank im Voraus!

p.s. Ich habe gesucht und nach einer Antwort gesucht! Ich bin überzeugt, dass es nicht einmal für alle Ergebnisse möglich ist!

Edit: Also die Idee davon ist zu sehen, wo einige bestimmte Punkte innerhalb der Struktur der 300k Probe liegen. Hier ist ein Beispieldiagramm, meine Punkte sind in drei Diff verteilt. Farben. My scatter version of the data

Ich werde versuchen, 1000 Datenpunkte aus meinen Daten nach dem Zufallsprinzip zu probieren und es als Textdatei hochladen. Cheers Stapler. :)

Edit: Hey, Hier sind einige Beispieldaten 1000 Zeilen - nur zwei Spalten [X,Y] (oder [g-i,i] von Plot oben) Raum begrenzt. Danke euch allen! the data

+2

Je nachdem, wie voll diese Werte sind, könnten Sie wahrscheinlich eine gewisse Struktur herauszukitzeln von nur tun, 'Streuung (x, y, alpha = 0,1)' oder einen geeigneten kleinen Wert. Um das zu tun, was Sie vorschlagen, würde ich eine Kernel-Dichte-Schätzung erstellen (siehe 'scipy.stats.kde'). – chthonicdaemon

+3

Warum verwenden Sie kein 2D-Histogramm, um Ihre Daten anzuzeigen? –

+1

@FriskyGrub Sie können nur zufällige Daten des gleichen Typs/Form/etc als Ihre realen Daten liefern - Sie müssen nicht immer die komplizierten Schritte posten, die die echten Daten an erster Stelle generiert haben. Es erleichtert uns, Ihnen nützliche Antworten zu geben. – YXD

Antwort

0

4 Jahre später und ich kann endlich antworten! Dies kann mit contains_points von matplotlib.path erfolgen.

Ich habe eine Gaußsche Glättung von astropy verwendet, die bei Bedarf weggelassen oder ersetzt werden kann.

import matplotlib.colors as colors 
from matplotlib import path 
import numpy as np 
from matplotlib import pyplot as plt 
try: 
    from astropy.convolution import Gaussian2DKernel, convolve 
    astro_smooth = True 
except ImportError as IE: 
    astro_smooth = False 

np.random.seed(123) 
t = np.linspace(-1,1.2,2000) 
x = (t**2)+(0.3*np.random.randn(2000)) 
y = (t**5)+(0.5*np.random.randn(2000)) 

H, xedges, yedges = np.histogram2d(x,y, bins=(50,40)) 
xmesh, ymesh = np.meshgrid(xedges[:-1], yedges[:-1]) 

# Smooth the contours (if astropy is installed) 
if astro_smooth: 
    kernel = Gaussian2DKernel(stddev=1.) 
    H=convolve(H,kernel) 

fig,ax = plt.subplots(1, figsize=(7,6)) 
clevels = ax.contour(xmesh,ymesh,H.T,lw=.9,cmap='winter')#,zorder=90) 

# Identify points within contours 
p = clevels.collections[0].get_paths() 
inside = np.full_like(x,False,dtype=bool) 
for level in p: 
    inside |= level.contains_points(zip(*(x,y))) 

ax.plot(x[~inside],y[~inside],'kx') 
plt.show(block=False) 

enter image description here

1

Sie können dies erreichen, mit einer Vielzahl von numpy/scipy/matplotlib Werkzeuge:

  1. für schnelles Nachschlagen eines scipy.spatial.KDTree der ursprünglichen Punkte erstellen.
  2. Verwenden np.meshgrid ein Gitter von Punkten bei der Auflösung Sie die Kontur
  3. Verwendung erstellen möchten KDTree.query eine Maske aller Standorte erstellen, die
  4. Bin die Daten innerhalb der Zieldichte sind, entweder mit einem rechteckigen Behälter oder plt.hexbin .
  5. Die Kontur aus den gruppierten Daten plotten, aber die Maske aus Schritt 3 verwenden, um die Regionen mit geringerer Dichte herauszufiltern.
  6. Verwenden Sie die Inverse der Maske zu plt.scatter die restlichen Punkte.
+0

Ich habe das nicht direkt versucht, aber das ist im Wesentlichen, was ich getan habe. Ich griff auf ein Hexbin-Heat-Plot zurück, weil ich die Berechnungszeit des Kontour-Materials von der Ordnung n^n -_- nicht reduzieren konnte ... es könnte sich lohnen, zurückzugehen, und es war ein lustiges Problem. – FriskyGrub