Seite 1 von 1

Werte in 2 Listen schnell addieren

Verfasst: Mittwoch 20. Mai 2009, 07:50
von feldmaus
Hallöle Alle,

Wie häufig sollte man an einem Tag eigentlich Hallo sagen ? :-)

Also ich habe 2 Listen, deren Werte ich index für index addieren
will zu einer neuen Liste.
Also:
a=[1,4]
b=[2,3]
a+b=[3,7]

Ich nehme an da gibt es eine schnelle Methode für ?
Ich habe mehrere 10000 Werte in mehreren Listen in einem größeren
Programm.

Grüße Markus

Verfasst: Mittwoch 20. Mai 2009, 07:59
von feldmaus
Vielleicht sollte ich an dieser Stelle aus performance Gründen einen
Code Schnippsel zeigen:

Code: Alles auswählen

        self.subplot1.bar(range(nitems),self.a_p_1.tolist(), color='red')
        self.subplot1.bar(range(nitems),self.a_p_2.tolist(), color='green',
                          bottom=self.a_p_1.tolist())
        self.subplot1.bar(range(nitems),self.a_p_3.tolist(), clor='blue',
                          bootom=self.a_p_1.tolist()+self.a_p_2.tolist())
Es werden 3 bar() Elemente in einer Grafik dargestellt. Das zweite
bar() Element fängt in y Richtung erst da an wo das erste bar() Element
aufhört. Dadurch verhindert man, dass die bar() Elemente hintereinander
liegen, d.h. ich setze die bar() Elemente aufeinander.
Das gleiche mache in mit dem dritten bar() Element, allerdings
muss ich dazu die Höhe des ersten und zweiten bar() Elementes
addieren. Da es viele Werte in meinen Array's gibt, sollte dies
möglichst effizient gelöst werden.
Meine Array sind:
self.a_p_1, self.a_p_2, self.a_p_3
Dort sind binäre Werte gespeichert.

Hat da jemand einen Tipp für mich ?

Grüße Markus

Verfasst: Mittwoch 20. Mai 2009, 08:04
von frabron
Zu deinem ersten Post ist mir spontan

Code: Alles auswählen

    a = (1,2)
    b = (3,4)
    for index in range(0, len(a)):
        print b[index]
eingefallen. Der zweite sagt mir jetzt grad gar nix, aber ich fange ja auch erst an mit Python ;)

Verfasst: Mittwoch 20. Mai 2009, 08:06
von Darii
Am unkompliziertesten mit am wenigsten nachdenken geht das so:

Code: Alles auswählen

from numpy import array
a = array([1,4])
b = array([2,3])
print a + b
Wenn du mit den selben Listen mehrmals rechnen musst ist das sicherlich auch die schnellste Methode.

Oder ohne externe Abhängigkeiten:

Code: Alles auswählen

print [x + y for x, y in zip(a,b)] # bei dir ist dann vermutlich izip aus den itertools schneller

Verfasst: Mittwoch 20. Mai 2009, 08:08
von feldmaus
frabron hat geschrieben:Zu deinem ersten Post ist mir spontan

Code: Alles auswählen

    a = (1,2)
    b = (3,4)
    for index in range(0, len(a)):
        print b[index]
eingefallen. Der zweite sagt mir jetzt grad gar nix, aber ich fange ja auch erst an mit Python ;)
Das mit der for Schleife wollte ich vermeiden, da ich viele Werte habe.

Im Prinzip will ich eine Vektoraddition, wobei meine Listen Vektoren
sind mit so vielen Komponenten, wie sie Werte haben.

Also Vektor a plus Vektor b gleich Vektor c.
Vektor a,b und c haben dabei gleich viele Werte.

Verfasst: Mittwoch 20. Mai 2009, 08:17
von Rebecca
Schau dir mal numpy an, das kennt Vektoren/Matrizen und die ueblichen Rechenoperationen darauf, und ich kann mir vorstellen, dass das recht gut optimiert ist.

Verfasst: Mittwoch 20. Mai 2009, 08:22
von feldmaus
Rebecca hat geschrieben:Schau dir mal numpy an, das kennt Vektoren/Matrizen und die ueblichen Rechenoperationen darauf, und ich kann mir vorstellen, dass das recht gut optimiert ist.
Ich finde die docu zu numpy nicht auf der Seite http://docs.python.org/.
Dort finde ich nur 4 Einträge zu numpy, die mir nicht sinnvoll erscheinen.

Grüße Markus

Verfasst: Mittwoch 20. Mai 2009, 08:31
von BlackJack
@feldmann_markus: Gibt es einen Grund warum Du in dem Quelltextschnippsel die `tolist()`-Methode aufrufst?

`numpy` ist auch nicht in der Standardbibliothek.

Verfasst: Mittwoch 20. Mai 2009, 08:57
von CM
edit: Unsinn gelöscht :oops:

@feldmann_markus: numpy ist genau für Deine Probleme gemacht und definitiv performant! Du findest es hier:
http://www.scipy.org/Download
zusammen mit scipy - was Du Dir vielleicht auch mal anschauen solltest.

Deine Lösung, wenn mein Raten auf array.array richtig ist, ist definitiv langsam.

Gruß,
Christian

Verfasst: Mittwoch 20. Mai 2009, 09:24
von feldmaus
BlackJack hat geschrieben:@feldmann_markus: Gibt es einen Grund warum Du in dem Quelltextschnippsel die `tolist()`-Methode aufrufst?.
Ja ich benötige eine Liste für die bar() Elemente und zwar eine laaange Liste.

Verfasst: Mittwoch 20. Mai 2009, 09:31
von feldmaus
CM hat geschrieben:Deine Lösung, wenn mein Raten auf array.array richtig ist, ist definitiv langsam.
Du tippst richtig. :-)
Ich dachte allerdings array.array würde aus numpy kommen.

Kann ich mit numpy denn auch binäre Werte aus Daten laden ?
In der Docu finde ich nichts equivalentes zu,

Code: Alles auswählen

a = array.array('b')
a.fromfile(f, n)

Verfasst: Mittwoch 20. Mai 2009, 09:51
von feldmaus
Ich habe das ganze jetzt mal ein wenig optimiert mit numpy, weiß
aber nicht ob der eine oder andere einen Verbesserungs-Voschlag hat ?

hier mein Code Schnippsel:

Code: Alles auswählen

        if not hasattr(self, 'subplot1'):
            self.subplot1 = self.figure.add_subplot(211)
            self.subplot2 = self.figure.add_subplot(212)
        nitems = 1000
        self.a_p_1.fromfile(self.f_peaks_1,nitems)
        self.a_p_2.fromfile(self.f_peaks_2,nitems)
        self.a_p_3.fromfile(self.f_peaks_3,nitems)
        self.a_pv_1.fromfile(self.f_peakvalue_1,nitems*2)#real + imag part
        self.a_pv_2.fromfile(self.f_peakvalue_2,nitems*2)
        self.a_pv_3.fromfile(self.f_peakvalue_3,nitems*2)
        d = range(nitems)
        a = np_array(self.a_p_1.tolist())
        b = np_array(self.a_p_2.tolist())
        c = np_array(self.a_p_3.tolist())
        bar1 = self.subplot1.bar(d,a, color='red', align='center')
        bar2 = self.subplot1.bar(d,b, color='green', align='center',
                                 bottom=a)
        bar3 = self.subplot1.bar(d,c, color='blue', align='center',
                                 bottom=a+b)
Die array.array Methode benötige ich aber trotzdem zum laden der
Werte aus den binären Dateien.

Vielleicht hat da Jemand einen schnelleren Vorschlag ?

Grüße Markus

Verfasst: Mittwoch 20. Mai 2009, 09:58
von BlackJack
Hier hättest Du die `tolist()`-Methode jetzt nicht gebraucht, das ist nur ein unnötiger Zwischenschritt.

Aber Du solltest Dir mal `numpy.fromfile()` anschauen. Das ist echt nicht zu finden gewesen? :-)

Verfasst: Mittwoch 20. Mai 2009, 11:51
von CM
Was bitte ist bei Dir "binär"? numpy.fromfile() kann sehr wohl binäre Daten lesen. Wie sieht denn Deine Datei aus (Beschreibung, bitte keine wirklich binären Daten posten)? Hast Du Die Datei selber erstellt? Wie? (Vielleicht kann man da drehen, so dass es leichter / schneller zu lesen ist.) Wie ist der dtype Deiner arrays? Z.B. 'complex128'?

Vorschläge:
- ebenso wie BJ: Lass das .tolist() weg - das braucht man gaaanz selten wirklich.
- die fromfile-Aufrufe sehen seltsam aus: Brauchst Du da wirklich keine Zuweisung?
- Ich würde ja plotting und Datenbearbeitung trennen. Das sind zwei Paar Schuhe und das Leben ist einfacher, wenn man diese Dinge trennt.

HTH
Christian

Verfasst: Mittwoch 20. Mai 2009, 12:29
von feldmaus
CM hat geschrieben:Was bitte ist bei Dir "binär"?

3 meiner Dateien enthalten nur:
(bin)00000000 --> 0(dez)
ODER
(bin)00000001 --> 1(dez)
die anderen 3 dateien enthalten:
00000000 00000000 00000000 00000000 --> 32bit float Zahl(Real Anteil)
UND
00000000 00000000 00000000 00000000 --> 32bit float Zahl(Imag Anteil)
Also ein Datensatz würde in den ersten 3 Dateien 8bit haben und in den
anderen 3 Dateien 64bit haben.
CM hat geschrieben:numpy.fromfile() kann sehr wohl binäre Daten lesen. Wie sieht denn Deine Datei aus (Beschreibung, bitte keine wirklich binären Daten posten)? Hast Du Die Datei selber erstellt? Wie? (Vielleicht kann man da drehen, so dass es leichter / schneller zu lesen ist.) Wie ist der dtype Deiner arrays? Z.B. 'complex128'?

Sieh oben. Die Dateien werden von einem OpenSource Programm
namens Gnuradio erstellt. Der Source Code ist in C++. Bitte verschont
mich. :-) Es wäre möglich eigene Module für Gnuradio zu programmieren,
wenn man genügend zeit und Erfahrung hat, die die Daten anders
ablegen.
CM hat geschrieben:Vorschläge:
- ebenso wie BJ: Lass das .tolist() weg - das braucht man gaaanz selten wirklich.
- die fromfile-Aufrufe sehen seltsam aus: Brauchst Du da wirklich keine Zuweisung?
- Ich würde ja plotting und Datenbearbeitung trennen. Das sind zwei Paar Schuhe und das Leben ist einfacher, wenn man diese Dinge trennt.
Hi und danke für die Antwort,

ich habe einige Kritik Punkte von Euch geändert.

mein jetziger Code Ausschnitt sieht wie folgt aus:

Code: Alles auswählen

class GraphWindow(wx.Window):
    def __init__(self, *args, **kwargs):
        wx.Window.__init__(self, *args, **kwargs)
        self.lines = []
        self.figure = Figure()
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        f_p_1 = file('../../../peakdetektor1.hex','rb')
        f_p_2 = file('../../../peakdetektor2.hex','rb')
        f_p_3 = file('../../../peakdetektor3.hex','rb')
        f_pv_1 = file('../../../peakband1.hex','rb')
        f_pv_2 = file('../../../peakband2.hex','rb')
        f_pv_3 = file('../../../peakband3.hex','rb')
        nitems = 1000
        self.a_p_1 = numpy.fromfile(f_p_1,dtype='b',count=nitems)
        self.a_p_2 = numpy.fromfile(f_p_2,dtype='b',count=nitems)
        self.a_p_3 = numpy.fromfile(f_p_3,dtype='b',count=nitems)
        self.a_pv_1 = numpy.fromfile(f_p_1,dtype='f',count=nitems*2)#real + imag part
        self.a_pv_2 = numpy.fromfile(f_p_1,dtype='f',count=nitems*2)
        self.a_pv_3 = numpy.fromfile(f_p_1,dtype='f',count=nitems*2)
        self.draw(nitems)

    def draw(self,nitems):
        if not hasattr(self, 'subplot1'):
            self.subplot1 = self.figure.add_subplot(211)
            self.subplot2 = self.figure.add_subplot(212)
        d = range(nitems)
        a = self.a_p_1
        b = self.a_p_2
        c = self.a_p_3
        bar1 = self.subplot1.bar(d,a, color='red', edgecolor='red',align='center')
        bar2 = self.subplot1.bar(d,b, color='green', edgecolor='green',align='center',
                                 bottom=a)
        bar3 = self.subplot1.bar(d,c, color='blue', edgecolor='blue',align='center',
                                 bottom=a+b)
Danke für die Tipps und Antworten Grüße Markus

Verfasst: Mittwoch 20. Mai 2009, 15:38
von CM
Hübsch ;-)

Und in einem nächsten Schritt würde ich die festen Verdrahtungen der Dateinamen lösen und einen Filedialog implementieren. Außerdem würde ich PATH so erweiteren, dass es Dein Programm erkennt. Arbeitest Du unter der bash?, dann ginge das so:

Code: Alles auswählen

export PATH=$PATH:/home/dein_user_name/rest/des/pfads
Diese Zeile in die .bashrc einstellen.

Das ist jetzt von mir ins Blaue geschossen und vielleicht Eulen nach Athen getragen, in dem Fall einfach ignorieren.

Jedenfalls könntest Du Dein Programm so in jedem Verzeichnis aufrufen - auch im Datenverzeichnis und ggf. auch die Dateien in der Kommandozeile mitgeben und über sys.argv ansprechen ...

HTH
Christian

Verfasst: Mittwoch 20. Mai 2009, 16:01
von feldmaus
CM hat geschrieben:Jedenfalls könntest Du Dein Programm so in jedem Verzeichnis aufrufen - auch im Datenverzeichnis und ggf. auch die Dateien in der Kommandozeile mitgeben und über sys.argv ansprechen ...
Wenn ich zeit habe, dann mache ich das nochmal. Allerdings habe ich ja
relative Pfade benutzt. Schließlich ändere ich meinen Ordner mit
den Dateien jeden Tag. :-) Aus Backup Gründen und um Korrekturen
rückgängig machen zu können.

Danke und Grüße Markus

Verfasst: Mittwoch 20. Mai 2009, 17:40
von Leonidas
feldmann_markus hat geschrieben:Schließlich ändere ich meinen Ordner mit
den Dateien jeden Tag. :-) Aus Backup Gründen und um Korrekturen
rückgängig machen zu können.
Dann solltest du besser Mercurial verwenden, statt den Ordner zu wechseln.

Verfasst: Donnerstag 21. Mai 2009, 01:35
von cofi
Wobei sich auch Git anbietet ;)
(Andere DVCS lass ich mal aussen vor, da ich nur mit den beiden Erfahrungen gemacht hab)

VCS erleichtern Projekte einfach unglaublich .. und da du ja an einem größeren arbeitest rennst du momentan ohne eines womöglich ins Verderben.