Interaktives großes Grundstück mit ~ 20 Millionen Abtastpunkten und Gigabyte Daten

80

Ich habe hier ein Problem (mit meinem RAM): Es kann die Daten, die ich zeichnen möchte, nicht speichern. Ich habe genügend HD-Speicherplatz. Gibt es eine Lösung, um dieses "Abschatten" meines Datensatzes zu vermeiden?

Konkret beschäftige ich mich mit digitaler Signalverarbeitung und muss eine hohe Abtastrate verwenden. Mein Framework (GNU Radio) speichert die Werte (um zu viel Speicherplatz zu vermeiden) in Binärform. Ich packe es aus. Danach muss ich planen. Ich brauche die Handlung zoombar und interaktiv. Und das ist ein Problem.

Gibt es ein Optimierungspotential für diese oder eine andere Software / Programmiersprache (wie R oder so), die größere Datenmengen verarbeiten kann? Eigentlich möchte ich viel mehr Daten in meinen Plots. Ich habe aber keine Erfahrung mit anderer Software. GNUplot schlägt mit einem ähnlichen Ansatz wie dem folgenden fehl. Ich kenne R (Jet) nicht.

import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import struct

"""
plots a cfile

cfile - IEEE single-precision (4-byte) floats, IQ pairs, binary
txt - index,in-phase,quadrature in plaintext

note: directly plotting with numpy results into shadowed functions
"""

# unpacking the cfile dataset
def unpack_set(input_filename, output_filename):
    index = 0   # index of the samples
    output_filename = open(output_filename, 'wb')

    with open(input_filename, "rb") as f:

        byte = f.read(4)    # read 1. column of the vector

        while byte != "":
        # stored Bit Values
            floati = struct.unpack('f', byte)   # write value of 1. column to a variable
            byte = f.read(4)            # read 2. column of the vector
            floatq = struct.unpack('f', byte)   # write value of 2. column to a variable
            byte = f.read(4)            # next row of the vector and read 1. column
            # delimeter format for matplotlib 
            lines = ["%d," % index, format(floati), ",",  format(floatq), "\n"]
            output_filename.writelines(lines)
            index = index + 1
    output_filename.close
    return output_filename.name

# reformats output (precision configuration here)
def format(value):
    return "%.8f" % value            

# start
def main():

    # specify path
    unpacked_file = unpack_set("test01.cfile", "test01.txt")
    # pass file reference to matplotlib
    fname = str(unpacked_file)
    plt.plotfile(fname, cols=(0,1)) # index vs. in-phase

    # optional
    # plt.axes([0, 0.5, 0, 100000]) # for 100k samples
    plt.grid(True)
    plt.title("Signal-Diagram")
    plt.xlabel("Sample")
    plt.ylabel("In-Phase")

    plt.show();

if __name__ == "__main__":
    main()

So etwas wie plt.swap_on_disk () könnte das Zeug auf meiner SSD zwischenspeichern;)

Wishi
quelle
Was meinst du mit "direktes Zeichnen mit numpy Ergebnissen in Schattenfunktionen" ?
JFS
2
Ich verstehe nicht, wie Sie "Gigabyte" an Daten erhalten. 20 Millionen x (3 x (4 Bytes)) = 240 MB, richtig? Und @EOL ist völlig richtig - das Konvertieren all dieser perfekt guten Binärdaten in ein Textformat ist reine Zeitverschwendung und E / A, verwenden Sie numpy, um direkt auf die Binärdatei zuzugreifen.
Jonathan Dursi
Seltsam, ich sehe dich nirgendwo Floati und Floatq lagern? Oder soll die Zeile, die mit "Zeilen" beginnt, innerhalb der while-Schleife liegen?
K.-Michael Aye
Interessant, dass ich es aufgrund der 6-Leerzeichen-Regel für Bearbeitungen nicht bearbeiten kann. Manchmal reichen 4 Leerzeichen aus, um den Code vollständig funktionsunfähig zu machen ...;)
K.-Michael Aye

Antworten:

90

Ihre Daten sind also nicht so groß, und die Tatsache, dass Sie Probleme beim Plotten haben, weist auf Probleme mit den Tools hin. Matplotlib hat viele Optionen und die Ausgabe ist in Ordnung, aber es ist ein riesiger Speicherfresser und es wird grundsätzlich davon ausgegangen, dass Ihre Daten klein sind. Es gibt aber auch andere Möglichkeiten.

Als Beispiel habe ich eine 20-Millionen-Datenpunktdatei 'bigdata.bin' mit den folgenden Methoden generiert:

#!/usr/bin/env python
import numpy
import scipy.io.numpyio

npts=20000000
filename='bigdata.bin'

def main():
    data = (numpy.random.uniform(0,1,(npts,3))).astype(numpy.float32)
    data[:,2] = 0.1*data[:,2]+numpy.exp(-((data[:,1]-0.5)**2.)/(0.25**2))
    fd = open(filename,'wb')
    scipy.io.numpyio.fwrite(fd,data.size,data)
    fd.close()

if __name__ == "__main__":
    main()

Dies erzeugt eine Datei mit einer Größe von ~ 229 MB, die nicht allzu groß ist. Sie haben jedoch zum Ausdruck gebracht, dass Sie zu noch größeren Dateien wechseln möchten, sodass Sie schließlich an Speichergrenzen stoßen.

Konzentrieren wir uns zunächst auf nicht interaktive Diagramme. Das erste, was zu erkennen ist, ist, dass Vektordiagramme mit Glyphen an jedem Punkt eine Katastrophe darstellen werden - für jeden der 20 M-Punkte, von denen sich die meisten ohnehin überlappen und versuchen, kleine Kreuze oder Kreise zu rendern, oder etwas geht eine Katastrophe zu sein, riesige Dateien zu generieren und jede Menge Zeit in Anspruch zu nehmen. Ich denke, das ist es, was Matplotlib standardmäßig versenkt.

Gnuplot hat keine Probleme damit:

gnuplot> set term png
gnuplot> set output 'foo.png'
gnuplot> plot 'bigdata.bin' binary format="%3float32" using 2:3 with dots

Gnuplot

Und selbst Matplotlib kann dazu gebracht werden, sich mit einiger Vorsicht zu verhalten (Auswahl eines Raster-Backends und Verwendung von Pixeln zum Markieren von Punkten):

#!/usr/bin/env python
import numpy
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

datatype=[('index',numpy.float32), ('floati',numpy.float32), 
        ('floatq',numpy.float32)]
filename='bigdata.bin'

def main():
    data = numpy.memmap(filename, datatype, 'r') 
    plt.plot(data['floati'],data['floatq'],'r,')
    plt.grid(True)
    plt.title("Signal-Diagram")
    plt.xlabel("Sample")
    plt.ylabel("In-Phase")
    plt.savefig('foo2.png')

if __name__ == "__main__":
    main()  

matplotlib

Wenn Sie jetzt interaktiv sein möchten, müssen Sie die zu plottenden Daten ablegen und im Handumdrehen vergrößern. Ich kenne keine Python-Tools, die Ihnen dabei helfen könnten.

Auf der anderen Seite ist das Plotten von Big Data eine ziemlich häufige Aufgabe, und es gibt Tools, die für diesen Job geeignet sind. Paraview ist mein persönlicher Favorit und VisIt ist ein anderer. Beide sind hauptsächlich für 3D-Daten gedacht, aber Paraview unterstützt insbesondere auch 2D-Daten und ist sehr interaktiv (und verfügt sogar über eine Python-Skriptoberfläche). Der einzige Trick besteht darin, die Daten in ein Dateiformat zu schreiben, das Paraview leicht lesen kann.

Jonathan Dursi
quelle
2
Guter Eintrag. +1 für VisIt- und ParaView-Erwähnungen - beide sind nützliche und leistungsstarke Visualisierungsprogramme, die für (sehr!) Große Datenmengen entwickelt wurden. Beachten Sie, dass VisIt auch über eine Python-Skriptschnittstelle verfügt und zusätzlich zu 2D- und 3D-Plots (Kurven) 1D zeichnen kann. In Bezug auf ein Dateiformat ist VTK ein relativ einfaches Format, das beide Programme unterstützen (tatsächlich basiert ParaView auf der VTK-Bibliothek).
Chris
2
Schauen Sie sich Bokeh Datashader an, der "selbst die größten Daten in Bilder verwandelt": github.com/bokeh/datashader
tommy.carstensen
3
Vielen Dank, dass Sie Paraview und VisIt erwähnt haben. Beide haben es geschafft, meinen 2D-Anwendungsfall abzudecken, der unter
Ciro Santilli
40

Eine Umfrage zu Open Source Interactive Plotting-Software mit einem 10-Millionen-Punkte-Streudiagramm-Benchmark unter Ubuntu

Inspiriert von dem Anwendungsfall, der unter folgender Adresse beschrieben wird: /stats/376361/how-to-find-the-sample-points-that-have-statistic-meaningful-large-outlier-r Ich habe ein Benchmarking durchgeführt Einige Implementierungen mit den folgenden sehr einfachen und naiven geraden 10-Millionen-Punkt-Daten:

i=0;
while [ "$i" -lt 10000000 ]; do
  echo "$i,$((2 * i)),$((4 * i))"; i=$((i + 1));
done > 10m.csv

Die ersten paar Zeilen 10m.csvsehen so aus:

0,0,0
1,2,4
2,4,8
3,6,12
4,8,16

Grundsätzlich wollte ich:

  • Erstellen Sie ein XY-Streudiagramm mehrdimensionaler Daten, hoffentlich mit Z als Punktfarbe
  • Wählen Sie interaktiv einige interessante Punkte aus
  • Zeigen Sie alle Dimensionen der ausgewählten Punkte an (einschließlich mindestens X, Y und Z), um zu verstehen, warum sie in der XY-Streuung Ausreißer sind

Um zusätzlichen Spaß zu haben, habe ich auch einen noch größeren Datensatz von 1 Milliarde Punkten vorbereitet, falls eines der Programme die 10 Millionen Punkte verarbeiten könnte! CSV-Dateien wurden etwas wackelig, deshalb bin ich zu HDF5 übergegangen:

import h5py
import numpy

size = 1000000000

with h5py.File('1b.hdf5', 'w') as f:
    x = numpy.arange(size + 1)
    x[size] =  size / 2
    f.create_dataset('x', data=x, dtype='int64')
    y = numpy.arange(size + 1) * 2
    y[size] =  3 * size / 2
    f.create_dataset('y', data=y, dtype='int64')
    z = numpy.arange(size + 1) * 4
    z[size] = -1
    f.create_dataset('z', data=z, dtype='int64')

Dies erzeugt eine ~ 23GiB-Datei, die Folgendes enthält:

  • 1 Milliarde Punkte in einer geraden Linie ähnlich 10m.csv
  • Ein Ausreißerpunkt in der Mitte oben im Diagramm

Die Tests wurden in Ubuntu 18.10 durchgeführt, sofern in einem Unterabschnitt nichts anderes angegeben ist, in einem ThinkPad P51-Laptop mit Intel Core i7-7820HQ-CPU (4 Kerne / 8 Threads), 2x Samsung M471A2K43BB1-CRC-RAM (2x 16 GB), NVIDIA Quadro M1200 4 GB GDDR5-GPU.

Zusammenfassung der Ergebnisse

Dies ist, was ich in Anbetracht meines sehr spezifischen Testanwendungsfalls beobachtet habe und dass ich zum ersten Mal Benutzer vieler der getesteten Software bin:

Behandelt es 10 Millionen Punkte:

Vaex        Yes, tested up to 1 Billion!
VisIt       Yes, but not 100m
Paraview    Barely
Mayavi      Yes
gnuplot     Barely on non-interactive mode.
matplotlib  No
Bokeh       No, up to 1m
PyViz       ?
seaborn     ?

Hat es viele Funktionen:

Vaex        Yes.
VisIt       Yes, 2D and 3D, focus on interactive.
Paraview    Same as above, a bit less 2D features maybe.
Mayavi      3D only, good interactive and scripting support, but more limited features.
gnuplot     Lots of features, but limited in interactive mode.
matplotlib  Same as above.
Bokeh       Yes, easy to script.
PyViz       ?
seaborn     ?

Fühlt sich die GUI gut an (ohne Berücksichtigung einer guten Leistung):

Vaex        Yes, Jupyter widget
VisIt       No
Paraview    Very
Mayavi      OK
gnuplot     OK
matplotlib  OK
Bokeh       Very, Jupyter widget
PyViz       ?
seaborn     ?

Vaex 2.0.2

https://github.com/vaexio/vaex

Installieren Sie eine Hallo-Welt und lassen Sie sie wie folgt funktionieren: Wie wird in Vaex eine interaktive 2D-Streudiagramm-Zoom- / Punktauswahl durchgeführt?

Ich habe Vaex mit bis zu 1 Milliarde Punkten getestet und es hat funktioniert, es ist großartig!

Es ist "Python-scripted-first", was sich hervorragend für die Reproduzierbarkeit eignet und es mir ermöglicht, einfach mit anderen Python-Dingen zu kommunizieren.

Das Jupyter-Setup hat ein paar bewegliche Teile, aber als ich es mit virtualenv zum Laufen gebracht habe, war es erstaunlich.

So laden Sie unseren CSV-Lauf in Jupyter:

import vaex
df = vaex.from_csv('10m.csv', names=['x', 'y', 'z'],)
df.plot_widget(df.x, df.y, backend='bqplot')

und wir können sofort sehen:

Geben Sie hier die Bildbeschreibung ein

Jetzt können wir mit der Maus zoomen, schwenken und Punkte auswählen, und Aktualisierungen sind sehr schnell, alles in weniger als 10 Sekunden. Hier habe ich hineingezoomt, um einige einzelne Punkte zu sehen, und einige davon ausgewählt (schwach helleres Rechteck auf dem Bild):

Geben Sie hier die Bildbeschreibung ein

Nachdem die Auswahl mit der Maus getroffen wurde, hat dies genau den gleichen Effekt wie bei Verwendung der df.select()Methode. So können wir die ausgewählten Punkte extrahieren, indem wir Jupyter ausführen:

df.to_pandas_df(selection=True)

welches Daten mit Format ausgibt:

        x       y        z   index
0 4525460 9050920 18101840 4525460
1 4525461 9050922 18101844 4525461
2 4525462 9050924 18101848 4525462
3 4525463 9050926 18101852 4525463
4 4525464 9050928 18101856 4525464
5 4525465 9050930 18101860 4525465
6 4525466 9050932 18101864 4525466

Da 10 Millionen Punkte gut funktionierten, habe ich beschlossen, 1B Punkte auszuprobieren ... und es hat auch gut funktioniert!

import vaex
df = vaex.open('1b.hdf5')
df.plot_widget(df.x, df.y, backend='bqplot')

Um den Ausreißer zu beobachten, der auf dem ursprünglichen Plot unsichtbar war, können wir folgendermaßen vorgehen: Wie wird der Punktstil in einem vaex-interaktiven Jupyter-bqplot plot_widget geändert, um einzelne Punkte größer und sichtbar zu machen? und verwenden:

df.plot_widget(df.x, df.y, f='log', shape=128, backend='bqplot')

welches produziert:

Geben Sie hier die Bildbeschreibung ein

und nach Auswahl des Punktes:

Geben Sie hier die Bildbeschreibung ein

Wir erhalten die vollständigen Daten des Ausreißers:

   x          y           z
0  500000000  1500000000  -1

Hier ist eine Demo der Entwickler mit einem interessanteren Datensatz und mehr Funktionen: https://www.youtube.com/watch?v=2Tt0i823-ec&t=770

Getestet in Ubuntu 19.04.

VisIt 2.13.3

Webseite: https://wci.llnl.gov/simulation/computer-codes/visit

Lizenz: BSD

Entwickelt von Lawrence Livermore National Laboratory , einer nationalen Behörde für nukleare Sicherheit Sie können sich also vorstellen, dass 10 Millionen Punkte nichts dafür sind, wenn ich es zum Laufen bringen könnte.

Installation: Es gibt kein Debian-Paket. Laden Sie einfach die Linux-Binärdateien von der Website herunter. Läuft ohne Installation. Siehe auch: /ubuntu/966901/installing-visit

Basierend auf VTK , der Backend-Bibliothek, die viele der Hochleistungs-Grafiksoftware verwenden. Geschrieben in C.

Nachdem ich 3 Stunden mit der Benutzeroberfläche gespielt hatte, funktionierte sie und mein Anwendungsfall wurde wie folgt gelöst: /stats/376361/how-to-find-the-sample- Punkte-die-statistisch-aussagekräftige-große-Ausreißer-haben-r

So sieht es in den Testdaten dieses Beitrags aus:

Geben Sie hier die Bildbeschreibung ein

und ein Zoom mit einigen Tipps:

Geben Sie hier die Bildbeschreibung ein

und hier ist das Auswahlfenster:

Geben Sie hier die Bildbeschreibung ein

In Bezug auf die Leistung war VisIt sehr gut: Jeder Grafikvorgang dauerte entweder nur wenig oder war sofort. Wenn ich warten musste, wird eine "Verarbeitungs" -Nachricht mit dem Prozentsatz der verbleibenden Arbeit angezeigt, und die GUI ist nicht eingefroren.

Da 10m Punkte so gut funktionierten, habe ich auch 100m Punkte ausprobiert (eine 2,7G CSV-Datei), aber es ist abgestürzt / in einen seltsamen Zustand geraten, leider habe ich es mir angesehen htop als die 4 VisIt-Threads meinen gesamten 16-GiB-RAM in Anspruch nahmen und wahrscheinlich aufgrund dessen starben zu einem gescheiterten Malloc.

Die ersten Schritte waren etwas schmerzhaft:

  • Viele der Standardeinstellungen fühlen sich grausam an, wenn Sie kein Atombombeningenieur sind. Z.B:
    • Standardpunktgröße 1px (wird mit Staub auf meinem Monitor verwechselt)
    • Achsenskala von 0,0 bis 1,0: Wie werden die tatsächlichen Achsenzahlwerte im Visit-Plotprogramm anstelle von Brüchen von 0,0 bis 1,0 angezeigt?
    • Multi-Window-Setup, böse Multi-Popups, wenn Sie Datenpunkte auswählen
    • zeigt Ihren Benutzernamen und Ihr Plotdatum an (entfernen Sie mit "Steuerelemente"> "Anmerkung"> "Benutzerinformationen")
    • Die Standardeinstellungen für die automatische Positionierung sind schlecht: Legendenkonflikte mit Achsen, Titelautomatisierung konnte nicht gefunden werden, daher musste eine Beschriftung hinzugefügt und alles von Hand neu positioniert werden
  • Es gibt nur viele Funktionen, daher kann es schwierig sein, das zu finden, was Sie wollen
  • Das Handbuch war sehr hilfreich, aber es ist ein 386-seitiges PDF-Mammut mit dem bedrohlichen Datum "Oktober 2005 Version 1.5". Ich frage mich, ob sie damit Trinity entwickelt haben ! und es ist ein schönes Sphinx-HTML, das erstellt wurde, nachdem ich diese Frage ursprünglich beantwortet hatte
  • kein Ubuntu-Paket. Aber die vorgefertigten Binärdateien haben einfach funktioniert.

Ich schreibe diese Probleme zu:

  • Es gibt es schon so lange und es werden einige veraltete GUI-Ideen verwendet
  • Sie können nicht einfach auf die Plotelemente klicken, um sie zu ändern (z. B. Achsen, Titel usw.), und es gibt viele Funktionen, sodass es etwas schwierig ist, die gesuchte zu finden

Ich finde es auch toll, wie ein bisschen LLNL-Infrastruktur in dieses Repo gelangt. Siehe zum Beispiel docs / OfficeHours.txt und andere Dateien in diesem Verzeichnis! Es tut mir leid für Brad, der der "Montagmorgen-Typ" ist! Oh, und das Passwort für den Anrufbeantworter lautet "Kill Ed", vergessen Sie das nicht.

Paraview 5.4.1

Website: https://www.paraview.org/

Lizenz: BSD

Installation:

sudo apt-get install paraview

Entwickelt von Sandia National Laboratories , einem weiteren NNSA-Labor, erwarten wir erneut, dass es die Daten problemlos verarbeiten kann. Auch VTK basiert und in C ++ geschrieben, was weiter vielversprechend war.

Ich war jedoch enttäuscht: Aus irgendeinem Grund machten 10 Millionen Punkte die GUI sehr langsam und reagierten nicht mehr.

Mir geht es gut mit einem kontrollierten, gut beworbenen Moment "Ich arbeite jetzt, warte ein bisschen", aber die GUI friert ein, während das passiert? Inakzeptabel.

htop zeigte, dass Paraview 4 Threads verwendete, aber weder CPU noch Speicher maximal waren.

In Bezug auf die Benutzeroberfläche ist Paraview sehr schön und modern, viel besser als VisIt, wenn es nicht stottert. Hier ist es mit einer niedrigeren Punktzahl als Referenz:

Geben Sie hier die Bildbeschreibung ein

und hier ist die Tabellenkalkulationsansicht mit einer manuellen Punktauswahl:

Geben Sie hier die Bildbeschreibung ein

Ein weiterer Nachteil ist, dass Paraview im Vergleich zu VisIt keine Funktionen hatte, z.

Mayavi 4.6.2

Website: https://github.com/enthought/mayavi

Entwickelt von: Enthought

Installieren:

sudo apt-get install libvtk6-dev
python3 -m pip install -u mayavi PyQt5

Der VTK Python.

Mayavi scheint sich sehr auf 3D zu konzentrieren. Ich konnte nicht herausfinden, wie man 2D-Diagramme darin erstellt. Daher schneidet es leider nicht für meinen Anwendungsfall.

Um die Leistung zu überprüfen, habe ich das Beispiel von https://docs.enthought.com/mayavi/mayavi/auto/example_scatter_plot.html für 10 Millionen Punkte angepasst und es läuft einwandfrei ohne Verzögerung:

import numpy as np
from tvtk.api import tvtk
from mayavi.scripts import mayavi2

n = 10000000
pd = tvtk.PolyData()
pd.points = np.linspace((1,1,1),(n,n,n),n)
pd.verts = np.arange(n).reshape((-1, 1))
pd.point_data.scalars = np.arange(n)

@mayavi2.standalone
def main():
   from mayavi.sources.vtk_data_source import VTKDataSource
   from mayavi.modules.outline import Outline
   from mayavi.modules.surface import Surface
   mayavi.new_scene()
   d = VTKDataSource()
   d.data = pd
   mayavi.add_source(d)
   mayavi.add_module(Outline())
   s = Surface()
   mayavi.add_module(s)
   s.actor.property.trait_set(representation='p', point_size=1)
main()

Ausgabe:

Geben Sie hier die Bildbeschreibung ein

Ich konnte jedoch nicht genug hineinzoomen, um einzelne Punkte zu sehen, die nahe 3D-Ebene war zu weit. Vielleicht gibt es einen Weg?

Eine coole Sache an Mayavi ist, dass Entwickler viel Mühe darauf verwenden, dass Sie die GUI von einem Python-Skript aus gut starten und einrichten können, ähnlich wie Matplotlib und Gnuplot. Es scheint, dass dies auch in Paraview möglich ist, aber die Dokumente sind zumindest nicht so gut.

Im Allgemeinen fühlt es sich als VisIt / Paraview nicht besonders gut an. Zum Beispiel konnte ich eine CSV nicht direkt von der GUI laden : Wie lade ich eine CSV-Datei von der Mayavi-GUI?

Gnuplot 5.2.2

Website: http://www.gnuplot.info/

Gnuplot ist sehr praktisch, wenn ich schnell und schmutzig werden muss, und es ist immer das erste, was ich versuche.

Installation:

sudo apt-get install gnuplot

Für den nicht interaktiven Gebrauch können 10 m Punkte ziemlich gut verarbeitet werden:

#!/usr/bin/env gnuplot
set terminal png size 1024,1024
set output "gnuplot.png"
set key off
set datafile separator ","
plot "10m1.csv" using 1:2:3:3 with labels point

das endete in 7 Sekunden:

Geben Sie hier die Bildbeschreibung ein

Aber wenn ich versuche, interaktiv zu werden

#!/usr/bin/env gnuplot
set terminal wxt size 1024,1024
set key off
set datafile separator ","
plot "10m.csv" using 1:2:3 palette

und:

gnuplot -persist main.gnuplot

dann fühlen sich das anfängliche Rendern und Zoomen zu träge an. Ich kann nicht einmal die Rechteckauswahllinie sehen!

Beachten Sie auch, dass ich für meinen Anwendungsfall Hypertext-Labels wie folgt verwenden musste:

plot "10m.csv" using 1:2:3 with labels hypertext

Es gab jedoch einen Leistungsfehler mit der Beschriftungsfunktion, auch für nicht interaktives Rendern. Aber ich habe es gemeldet und Ethan hat es an einem Tag gelöst: https://groups.google.com/forum/#!topic/comp.graphics.apps.gnuplot/qpL8aJIi9ZE

Ich muss jedoch sagen, dass es eine vernünftige Problemumgehung für die Auswahl von Ausreißern gibt: Fügen Sie einfach allen Punkten Beschriftungen mit der Zeilen-ID hinzu! Wenn sich viele Punkte in der Nähe befinden, können Sie die Etiketten nicht lesen. Aber für die Ausreißer, die Sie interessieren, könnten Sie gerade! Wenn ich beispielsweise einen Ausreißer zu unseren Originaldaten hinzufüge:

cp 10m.csv 10m1.csv
printf '2500000,10000000,40000000\n' >> 10m1.csv

und ändern Sie den Plot-Befehl in:

#!/usr/bin/env gnuplot
set terminal png size 1024,1024
set output "gnuplot.png"
set key off
set datafile separator ","
plot "10.csv" using 1:2:3:3 palette with labels

Dies verlangsamte das Plotten erheblich (40 Minuten nach dem oben erwähnten Fix), führt jedoch zu einer angemessenen Ausgabe:

Geben Sie hier die Bildbeschreibung ein

Mit etwas Datenfilterung würden wir also irgendwann dorthin gelangen.

Matplotlib 1.5.1, numpy 1.11.1, Python 3.6.7

Website: https://matplotlib.org/

Matplotlib ist das, was ich normalerweise versuche, wenn mein Gnuplot-Skript zu verrückt wird.

numpy.loadtxt Allein dauerte es ungefähr 10 Sekunden, also wusste ich, dass das nicht gut gehen würde:

#!/usr/bin/env python3

import numpy
import matplotlib.pyplot as plt

x, y, z = numpy.loadtxt('10m.csv', delimiter=',', unpack=True)
plt.figure(figsize=(8, 8), dpi=128)
plt.scatter(x, y, c=z)
# Non-interactive.
#plt.savefig('matplotlib.png')
# Interactive.
plt.show()

Zuerst lieferte der nicht interaktive Versuch eine gute Ausgabe, dauerte aber 3 Minuten und 55 Sekunden ...

Dann dauerte das interaktive beim ersten Rendern und beim Zoomen lange. Nicht brauchbar:

Geben Sie hier die Bildbeschreibung ein

Beachten Sie auf diesem Screenshot, wie die Zoomauswahl, die sofort zoomen und verschwinden sollte, lange auf dem Bildschirm blieb, während sie auf die Berechnung des Zooms wartete!

Ich musste auskommentieren, plt.figure(figsize=(8, 8), dpi=128)damit die interaktive Version aus irgendeinem Grund funktioniert, sonst explodierte sie mit:

RuntimeError: In set_size: Could not set the fontsize

Bokeh 1.3.1

https://github.com/bokeh/bokeh

Ubuntu 19.04 installieren:

python3 -m pip install bokeh

Starten Sie dann Jupyter:

jupyter notebook

Wenn ich jetzt 1 m Punkte zeichne, funktioniert alles perfekt, die Benutzeroberfläche ist fantastisch und schnell, einschließlich Zoom- und Schwebefluginformationen:

from bokeh.io import output_notebook, show
from bokeh.models import HoverTool
from bokeh.transform import linear_cmap
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource
import numpy as np

N = 1000000
source = ColumnDataSource(data=dict(
    x=np.random.random(size=N) * N,
    y=np.random.random(size=N) * N,
    z=np.random.random(size=N)
))
hover = HoverTool(tooltips=[("z", "@z")])
p = figure()
p.add_tools(hover)
p.circle(
    'x',
    'y',
    source=source,
    color=linear_cmap('z', 'Viridis256', 0, 1.0),
    size=5
)
show(p)

Erste Ansicht:

Geben Sie hier die Bildbeschreibung ein

Nach einem Zoom:

Geben Sie hier die Bildbeschreibung ein

Wenn ich bis zu 10 m gehe, obwohl es erstickt, htopzeigt dies, dass Chrom 8 Threads hat, die meinen gesamten Speicher im unterbrechungsfreien E / A-Zustand belegen.

Hier wird nach der Referenzierung der Punkte gefragt: So referenzieren Sie ausgewählte Bokeh-Datenpunkte

PyViz

https://pyviz.org/

TODO bewerten.

Integriert Bokeh + Datashader + andere Tools.

Video-Demo von 1B-Datenpunkten: https://www.youtube.com/watch?v=k27MJJLJNT4 "PyViz: Dashboards zur Visualisierung von 1 Milliarde Datenpunkten in 30 Python-Zeilen" von "Anaconda, Inc." veröffentlicht am 17.04.2018.

Seaborn

https://seaborn.pydata.org/

TODO bewerten.

Es gibt bereits eine Qualitätssicherung zur Verwendung von Seaborn zur Visualisierung von mindestens 50 Millionen Zeilen .

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
1
Erstaunliches Schreiben! Vielen Dank, dass Sie die Vor- und Nachteile der einzelnen Lösungen zusammen mit dem Beispielcode aufgeführt haben!
gaborous
1
@gaborous fröhliches Plotten! :)
Ciro Santilli 15 冠状 病 六四 六四 15
13

Sie können das Lesen Ihrer Datei sicherlich optimieren: Sie können sie direkt in ein NumPy-Array einlesen, um die Geschwindigkeit von NumPy zu nutzen. Sie haben einige Möglichkeiten. Wenn RAM ein Problem darstellt, können Sie memmap verwenden , mit dem der größte Teil der Datei auf der Festplatte gespeichert wird (anstatt im RAM):

# Each data point is a sequence of three 32-bit floats:
data = np.memmap(filename, mode='r', dtype=[('index', 'float32'), ('floati','float32'), ('floatq', 'float32')])

Wenn RAM kein Problem darstellt, können Sie das gesamte Array mit fromfile in den RAM stellen :

data = np.fromfile(filename, dtype=[('index', 'float32'), ('floati','float32'), ('floatq', 'float32')])

Das Plotten kann dann mit der üblichen plot(*data)Funktion von Matplotlib erfolgen , möglicherweise durch die in einer anderen Lösung vorgeschlagene "Zoom" -Methode.

Eric O Lebigot
quelle
1
Wenn Sie ein strukturiertes Numpy-Array erstellen und eine Datei schreibgeschützt öffnen möchten, dann : np.memmap(filename, mode='r', dtype=[('floati','f'), ('floatq', 'f')]).
JFS
Ausgehend von 1 Million Doppelpunkten bekomme ich Agg-Überläufe in jedem Backend, das ich versucht habe, auch mit path.simplify = True. Ich glaube also nicht, dass es mit Matplotlib möglich sein wird, dies einfach so zu tun.
K.-Michael Aye
Interessant. Wie in Jonathan Dursis Antwort erwähnt, sind mit Matplotlib 20 Millionen Punkte erreichbar, jedoch mit einigen Einschränkungen (Rasterausgabe,…).
Eric O Lebigot
8

Ich würde etwas Komplexes vorschlagen, aber das sollte funktionieren: Erstellen Sie Ihr Diagramm mit unterschiedlichen Auflösungen für unterschiedliche Bereiche.

Denken Sie zum Beispiel an Google Earth. Wenn Sie die maximale Auflösung aufheben, um den gesamten Planeten abzudecken, ist die Auflösung am niedrigsten. Wenn Sie zoomen, ändern sich die Bilder für detailliertere, jedoch nur für die Region, auf die Sie zoomen.

Grundsätzlich schlage ich für Ihr Diagramm (2D? 3D? Ich nehme an, es ist 2D) vor, dass Sie ein großes Diagramm erstellen, das den gesamten [0, n] -Bereich mit niedriger Auflösung abdeckt, und 2 kleinere Diagramme, die [0, n] abdecken / 2] und [n / 2 + 1, n] mit der doppelten Auflösung des großen, 4 kleinere Graphen, die [0, n / 4] abdecken ... [3 * n / 4 + 1, n] mit der doppelten Auflösung die Auflösung der 2 oben und so weiter.

Ich bin mir nicht sicher, ob meine Erklärung wirklich klar ist. Ich weiß auch nicht, ob diese Art von Grafik mit mehreren Auflösungen von einem vorhandenen Plotprogramm verarbeitet wird.

user703016
quelle
In diesem Fall könnte ich einfach meine Abtastrate reduzieren ... aber ich brauche so viele Werte in einem interaktiven Plot.
Wishi
4
@wishi: Haben Sie wirklich brauchen Millionen von Wert in einem Grundstück, überlappen sich viele von denen man bedenkt? Die adaptive Auflösung erscheint mir vernünftig.
user703016
Keine Chance ... speziell ich nehme Echtzeitdaten auf, die in einem sehr kurzen Signalburst gekapselt sind. Das bedeutet alle Proben oder nichts. Sie können sich nicht an etwas anpassen, das Sie analysieren
möchten
12
Es ist nur eine Frage der Anzeige, nicht der Datenanalyse. Ihre Ergebnisse werden nicht beeinflusst, nur die Anzeige.
user703016
habe ein ähnliches Problem, aber ich habe Terra-Bytes von Daten über ein paar Jahre. (Sensordaten mit einer Abtastrate von 40 kHz). Jetzt möchte ich ein interaktives Diagramm haben, das so etwas wie einen Mittelwert für x Stunden oder sogar einen ganzen Tag darstellt. Wenn ich hineinzoome, sollten die neuen Mittelwerte dynamisch berechnet werden und so weiter, bis ich so weit gezoomt bin , dass keine Mittelwertberechnung erforderlich ist. Die Frage ist:
Gibt
2

Ich frage mich, ob es einen Gewinn gibt, wenn Sie die Suche nach Ihren Punkten beschleunigen. (Ich bin schon eine Weile von R * (r Stern) Bäumen fasziniert.)

Ich frage mich, ob die Verwendung von so etwas wie einem r * -Baum in diesem Fall der richtige Weg sein könnte. (Beim Herauszoomen können höher gelegene Knoten im Baum Informationen über das gröbere, herausgezoomte Rendering enthalten. Knoten weiter in Richtung der Blätter enthalten die einzelnen Stichproben.)

Vielleicht ordnet der Speicher den Baum (oder die Struktur, die Sie letztendlich verwenden) dem Speicher zu, um Ihre Leistung und Ihren RAM-Verbrauch gering zu halten. (Sie verlagern die Aufgabe der Speicherverwaltung in den Kernel.)

hoffe das macht Sinn .. ein bisschen streifen. es ist spät!

Nielsbot
quelle
Ich habe keine Ahnung von R. Mein Datensatz ähnelt einem CSV wie {index, floati, floatq}. Das wiederholt sich 20 Millionen Mal. Ich bin nicht sicher, wie Sie die Datenstruktur aufbauen würden, die Sie in R. erwähnen
Wishi
3
Ich denke, es könnte ein involviertes Projekt sein. Ich spreche von "R-Stern" -Bäumen. wikipedia: en.wikipedia.org/wiki/R * _tree HTH
nielsbot