2017-06-07 9 views
0

Für meine Auswertung habe ich gnuplot verwendet, um Daten aus zwei separaten csv-Dateien (in diesem Link: https://drive.google.com/open?id=0B2Iv8dfU4fTUZGV6X1Bvb3c4TWs) mit einer anderen Anzahl von Zeilen zu plotten, die das folgende Diagramm generiert.Python - Interpolation von Plots

enter image description here

Diese Daten scheinen keine gemeinsamen Zeitstempel (die erste Spalte) in beiden csv Dateien zu haben und noch gnuplot scheint das Plotten zu passen, wie oben gezeigt.

Hier ist das gnuplot Skript, das ich verwende, um mein Grundstück zu generieren.

# ###### GNU Plot 

set style data lines 
set terminal postscript eps enhanced color "Times" 20 

set output "output.eps" 

set title "Actual vs. Estimated Comparison" 

set style line 99 linetype 1 linecolor rgb "#999999" lw 2 
#set border 1 back ls 11 
set key right top 
set key box linestyle 50 
set key width -2 
set xrange [0:10] 
set key spacing 1.2 
#set nokey 

set grid xtics ytics mytics 
#set size 2 
#set size ratio 0.4 

#show timestamp 
set xlabel "Time [Seconds]" 
set ylabel "Segments" 

set style line 1 lc rgb "#ff0000" lt 1 pi 0 pt 4 lw 4 ps 0 

plot "estimated.csv" using ($1):2 with lines title "Estimated", "actual.csv" using ($1):2 with lines title "Actual"; 

Ich wollte meine grüne Linie in das Netz, wo meine rosa Linie definiert ist, dann vergleichen, die beiden zu interpolieren. Hier ist mein erster Ansatz

#!/usr/bin/env python 
import sys 

import numpy as np 
from shapely.geometry import LineString 
#------------------------------------------------------------------------------- 
def load_data(fname): 
    return LineString(np.genfromtxt(fname, delimiter = ',')) 
#------------------------------------------------------------------------------- 
lines = list(map(load_data, sys.argv[1:])) 

for g in lines[0].intersection(lines[1]): 
    if g.geom_type != 'Point': 
     continue 
    print('%f,%f' % (g.x, g.y)) 
Then in Gnuplot, one can invoke it directly: 

set terminal pngcairo 
set output 'fig.png' 

set datafile separator comma 
set yr [0:700] 
set xr [0:10] 

set xtics 0,2,10 
set ytics 0,100,700 

set grid 

set xlabel "Time [seconds]" 
set ylabel "Segments" 

plot \ 
    'estimated.csv' w l lc rgb 'dark-blue' t 'Estimated', \ 
    'actual.csv' w l lc rgb 'green' t 'Actual', \ 
    '<python filter.py estimated.csv actual.csv' w p lc rgb 'red' ps 0.5 pt 7 t '' 

, die uns die folgende Handlung gibt

enter image description here

ich die gefilterten Punkte auf eine andere Datei (filtered_points.csv in diesem Link: https://drive.google.com/open?id=0B2Iv8dfU4fTUSHVOMzYySjVzZWc) schrieb aus diesem Skript. Die gefilterten Punkte sind jedoch weniger als 10% des tatsächlichen Datensatzes (was die Grundwahrheit ist).

Gibt es eine Möglichkeit, wo wir die zwei Linien interpolieren können, indem Sie die pinkfarbenen hohen Spitzen über der grünen Kurve mit python ignorieren? scheint nicht das beste Werkzeug dafür zu sein. Wenn die rosa Linie die grüne Linie nicht berührt (dh, wenn sie weit unter der grünen Linie liegt), möchte ich die Werte der nächsten grünen Linie nehmen, so dass es eine Eins-zu-Eins-Übereinstimmung ist (oder sehr nahe) mit dem eigentlichen Datensatz. Ich möchte die interpolierten Werte für die grüne Linie im rosa Linienraster zurückgeben, so dass wir beide Linien vergleichen können, da sie dieselbe Array-Größe haben.

+1

Ich glaube, ich verstehe nicht, was du willst es wirklich tun. Was bedeutet "Ich wollte meine grüne Linie in das Gitter interpolieren, wo meine rosa Linie definiert ist, dann vergleiche die beiden." bedeuten? In meinem Verständnis magst du: 1. Passen Sie die grüne Kurve 2. Stellen Sie sicher, dass alle Ihre rosa Daten unter dem grünen 3. Vergleichen Sie die Daten und auf diese Weise suchen Sie nach Kreuzungen. 4. Geben Sie diese Schnittpunktdaten zurück Ist das richtig? Ist die grüne Kurve nicht schon voll, wonach Sie suchen? – Franz

+1

Welche Art von Interpolation? Linear? Splines? Andere? – Goyo

+0

@Franz, GENAU !!! Aber was ich schließlich wollte, ist eine Eins-zu-eins-Datengröße der grünen und rosa Linien. Wenn Sie die CSV-Dateien in diesem Link gesehen haben: https://drive.google.com/drive/folders/0B2Iv8dfU4fTUZGV6X1Bvb3c4TWs - wir haben mehr Datenpunkte in der Datei "geschätzt.csv" als in der Datei "aktuell.csv" (Grundwahrheit) . In diesem Fall möchte ich glätten, damit es so zur Grundwahrheit passt. Wenn es eine Lücke gibt (wie Sie aus dem Diagramm sehen können, sind einige Punkte unterhalb der grünen Linie - in diesem Fall nehmen wir den aktuellen Wert (Datenpunkt) der grünen Linie). Hoffe das erklärt. –

Antwort

1

Mit numpy.interp() die gleiche Datengröße in Bezug auf eine Interpolation zu erhalten ist ziemlich einfach. Für mich ist dieser Code funktioniert:

import numpy as np 
import matplotlib.pyplot as plt 

names = ['actual.csv','estimated.csv'] 
#------------------------------------------------------------------------------- 
def load_data(fname): 
    return np.genfromtxt(fname, delimiter = ',') 
#------------------------------------------------------------------------------- 

data = [load_data(name) for name in names] 
actual_data = data[0] 
estimated_data = data[1] 
interpolated_estimation = np.interp(estimated_data[:,0],actual_data[:,0],actual_data[:,1]) 

plt.figure() 
plt.plot(actual_data[:,0],actual_data[:,1], label='actual') 
plt.plot(estimated_data[:,0],estimated_data[:,1], label='estimated') 
plt.plot(estimated_data[:,0],interpolated_estimation, label='interpolated') 
plt.legend() 
plt.show(block=True) 

Nach dieser Interpolation interpolated_estimation die gleiche Größe wie der x-Achse von actual_data hat, wie die Handlung vermuten lässt. Das Schneiden ist ein wenig verwirrend, aber ich habe versucht, Ihre Funktion zu nutzen und die plot Anrufe so klar wie möglich zu machen.

enter image description here

in eine Datei und Handlung zu speichern, wie vorgeschlagen, dass ich den Code geändert:

import numpy as np 
import matplotlib.pyplot as plt 

names = ['actual.csv','estimated.csv'] 
#------------------------------------------------------------------------------- 
def load_data(fname): 
    return np.genfromtxt(fname, delimiter = ',') 
#------------------------------------------------------------------------------- 

data = [load_data(name) for name in names] 
actual_data = data[0] 
estimated_data = data[1] 
interpolated_estimation = np.interp(estimated_data[:,0],actual_data[:,0],actual_data[:,1]) 

plt.figure() 
plt.plot(actual_data[:,0],actual_data[:,1], label='actual') 
#plt.plot(estimated_data[:,0],estimated_data[:,1], label='estimated') 
plt.plot(estimated_data[:,0],interpolated_estimation, label='interpolated') 
np.savetxt('interpolated.csv', 
     np.vstack((estimated_data[:,0],interpolated_estimation)).T, 
     delimiter=',', fmt='%10.5f') #saves data to filedata to file 
plt.legend() 
plt.title('Actual vs. Interpolated') 
plt.xlim(0,10) 
plt.ylim(0,500) 
plt.xlabel('Time [Seconds]') 
plt.ylabel('Segments') 
plt.grid() 
plt.show(block=True) 

Dies erzeugt die folgende Ausgabe: enter image description here

+0

Danke Franz. Wird es möglich sein, die Datenpunkte des 'interpolierten' in eine andere Datei zu schreiben, so dass es leicht ist, zu sehen, ob es eine Eins-zu-Eins-Entsprechung gibt? Schließlich möchte ich ein Diagramm wie in dem folgenden Link generieren: https://drive.google.com/open?id=0B2Iv8dfU4fTUSHVOMzYySjVzZWc –

+0

Hallo Desta, ich habe die geänderte Quelle hinzugefügt. – Franz

+0

Ehrfürchtig. Ich habe deine Antwort akzeptiert Franz. Wenn Sie jedoch die Dateien 'actual.csv' (mit 15179 Zeilen) und' geschätzte.csv' (mit 258267 Zeilen) gesehen haben, gibt es zwei Spalten mit Daten, die durch ein Komma getrennt sind. Aber in der neuen Datei "interpolated.csv" gibt es etwa 516534 Zeilen mit einer Spalte Daten. Selbst die neuen Daten (zB die erste Zeile: 2.648999999999999879d-03) sind schwer zu interpretieren. Ist es möglich, zwei Spalten als Originaldatei zu haben und eine 1: 1-Übereinstimmung mit der 'actual.csv' herzustellen? Ich meine, die gleichen Zeilen wie 'actual.csv' zu haben? –