Mehrdimensionales Feld erstellen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
scoobydo
User
Beiträge: 5
Registriert: Sonntag 17. Februar 2013, 16:55

Hallo,

ich habe mal eine Frage und zwar will ich aus einer Wertetabelle (2D) die Werte auslesen und in
einer Matrix abspeichern.
Aus irgendeinem Grund will das aber nicht funktionieren.
Könnt ihr mir evtl. weiterhelfen?

Mein Code lautet:

Code: Alles auswählen

Messung=open("a1.txt","r")

l=Messung.readlines()                                                                                   
n=len(l) 

a= [[n],[1]]
for i in range(0,n,1):
    Spalte=l[i].rsplit()
    a[i][0]=Spalte[0]
    a[i][1]=Spalte[1]

Messung.close()
Die Tabelle würde z.B. so aussehen:
0.1 2
0.2 4
0.5 8

Als Fehlermeldung erhalte ich (auch bei diskreten Werten für n)

Code: Alles auswählen

 a[i][1]=Spalte[1]
IndexError: list assignment index out of range
Vielen Dank schon einmal
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@scoobydo: hast du das Tutorial gelesen?
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

@scoobydo: Und im Anschluss oder parallel dazu vielleicht noch den Style Guide for Python Code.

Dateien sollte man zusammen mit der ``with``-Anweisung verwenden.

Zugriffe über laufende Indizes sind in Python recht selten, weil man über Elemente in Sequenzen direkt iterieren kann, ohne einen Umweg über einen Index zu gehen. Über die Zeilen einer Datei kann man auch itierieren ohne sie erst alle in den Speicher lesen zu müssen. Listen werden in der Regel aufgebaut in dem man mit einer leeren Liste startet und die Elemente in einer Schleife an diese Liste anhängt. Wenn der Schleifeninhalt einfach ist, kann man oft auch eine kompakte „list comprehension” schreiben um eine Liste mit Werten zu erzeugen.
scoobydo
User
Beiträge: 5
Registriert: Sonntag 17. Februar 2013, 16:55

Da habe ich mich schon wundgesucht, das einzige was ich da finde sind
Erklärungen/Beispiele wie ich 1D Felder anlege bzw. auch direkt belege.

Aber ich möchte einfach nur ein 2D Feld erzeugen und nachträglich belegen.
BlackJack

@scoobydo: Ein „2D-Feld” ist ein „1D-Feld” das als Elemente wieder „1D-Felder” enhält. Wenn Du also 1D kannst, dann müsstest Du auch 2D können. Wobei wir hier von Listen reden, so heisst dieser Datentyp in Python nun einmal.

Und zumindest bei dem was Du bis jetzt gezeigt hast, ist nicht ersichtlich warum Du die Struktur *erst* erstellen und *dann* füllen musst, statt sie gleich mit den richtigen Werten zu erstellen. Python ist nicht C oder Pascal wo man erst einen Speicherbereich reserviert und den dann mit Daten füllt. Du brauchst zum Erstellen der ”leeren” Listenstruktur schon (mindestens) eine Schleife und zum befüllen dann das gleiche noch mal. Wo es eigentlich genügen würde gleich im ersten Durchgang die Listenstruktur mit den gewünschten Werten zu erstellen.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Mal so aus dem Stegreif:

Code: Alles auswählen

a = []
with open('a1.txt', 'r') as messungen:
    for messung in messungen:
        werte = messung.split()
        a.append(werte)
Was Du hier erhältst ist eine Liste mit Listen aller Werte, die sich pro Messzeile per split() separieren lassen.
scoobydo
User
Beiträge: 5
Registriert: Sonntag 17. Februar 2013, 16:55

Ah ok habe mal ein wenig damit "rumgespielt" und versucht die einzelenen Werte aufzurufen etc.
Habt vielen Dank!!!

Ich stelle mich mit Python ein wenig quer weil ich eigentlich nur, und sehr überzeugt, mit C programmiere und
dementsprechend auch denke.

Also noch mal besten Dank für die schnelle Hilfe :!:
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

scoobydo hat geschrieben:Ich stelle mich mit Python ein wenig quer weil ich eigentlich nur, und sehr überzeugt, mit C programmiere und dementsprechend auch denke.
Auch ich habe früher u.a. viel mit C/C++ gemacht und finde diese Sprachen als maschinennahe Programmiersprachen effizient und habe sie auch gerne genutzt. Python aber macht deutlich mehr Spaß, die Programme sind lesbarer, kompakter, und vom turnaround brauchen wir gar nicht erst zu reden. Meine Empfehlung: bleib dran. Auf C kannst Du immer noch zurückgreifen wenn's klemmt.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

scoobydo hat geschrieben:Ich stelle mich mit Python ein wenig quer weil ich eigentlich nur, und sehr überzeugt, mit C programmiere und dementsprechend auch denke.
Am besten, du betrachtest Python nicht als eine C-artige Sprache mit weniger Klammern, sondern als Lisp-artige Sprache mit weniger Klammern :wink:
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

Mit einer „list comprehension” und etwas mehr Gedanken bei den Namen:

Code: Alles auswählen

with open('a1.txt') as lines:
    messwerte = [line.split() for line in lines]
C finde ich auch gut. Wenn man mal Geschwindigkeit braucht oder auf Zielplattformen wo Python nicht läuft. :-)

@pillmuncher: Darf man Dich damit zitieren? :-D
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

BlackJack hat geschrieben:@pillmuncher: Darf man Dich damit zitieren? :-D
Aber freilich! :)
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

pillmuncher hat geschrieben:Am besten, du betrachtest Python nicht als eine C-artige Sprache mit weniger Klammern, sondern als Lisp-artige Sprache mit weniger Klammern :wink:
Das gefällt mir gut :)
scoobydo
User
Beiträge: 5
Registriert: Sonntag 17. Februar 2013, 16:55

Hey,

habe leider doch noch einmal eine Frage.
Und zwar will ich die eingelesenen Werte nun weiter bearbeiten und brauche sie somit als float-Werte.

Gibt es eine Möglich keit das elegant beim Einlesen einzuarbeiten?
Habe das jetzt so versucht:

Code: Alles auswählen

a= []                                                                                                   
for i in range(0,n,1):
    Wertepaar=l[i].rsplit()
    a.append([float(Wertepaar[0]),float(Wertepaar[1])])
Das Problem ist nur wenn ich jetzt meine Rechnung durchführen will, sagt er mir:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Users\Malte\Desktop\Tu-Messung\Tu-Auswertung.py", line 39, in <module>
    a[i][1]=pow(a[i][1],grad)*koef[j]
TypeError: 'float' object is not subscriptable
Mein komplettes Programm sieht wie folgt aus:

Code: Alles auswählen

a= []                                                                                                   #Daten einlesen
for i in range(0,n,1):
    Wertepaar=l[i].rsplit()
    a.append([float(Wertepaar[0]),float(Wertepaar[1])])

Messung.close()

#Kalibrierfunktion einlesen

grad=int(input("Bitte geben Sie den Grad des Kalibrierpolynoms ein: "))

print("Geben Sie nun die Koeffizienten absteigend an!")
koef=[]
for i in range(0,grad+1,1):
    print("Koeffizient ",grad-i," :")
    koef=float(input())

#Umrechnen der Spannungen in eine Geschwindigkeit

for i in range(0,n,1):
    for j in range(0,grad+1,1):
        if j==0:
            a[i][1]=pow(a[i][1],grad)*koef[j]
        else:
            a[i][1]=a[i][1]+pow(a[i][1],grad-j)*koef[j-1]
Vielen Dank schon einmal!
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Zerlege die Zeile, in der der Fehler auftritt, doch einfach mal in Teilschritte. Dann wirst du sehen, was nicht funktioniert. Eigentlich sagt die Fehlermeldung schon alles aus.
Das Leben ist wie ein Tennisball.
BlackJack

@scoobydo: Irgendwie hast Du so gut wie nichts von den Verbesserungsvorschlägen umgesetzt. Der Code ist immer noch voller Indexzugriffe. Das ist in Python unüblich, weil man direkt über Elemente iterieren kann. Und falls man *zusätzlich* einen Index benötigt, gibt es die `enumerate()`-Funktion. Python ist nicht C. Wenn man über mehrere Sequenzen parallel iterieren möchte, kann man die `zip()`-Funktion verwenden.

Zum Fehler: Schau Dir doch einfach mal an auf was Du hier alles den Index-Operator anwendest. Und welche Werte da jeweils hinter stehen. Dann findest Du schnell ein Objekt, dass gar nicht Indexierbar ist, weil es den Typ `float` hat. Also genau was die Fehlermeldung sagt. Und dann schaust Du wie dieser Wert zustande kommt und da sollte ziemlich offensichtlich sein warum das ein `float` ist. Weil da nämlich ein `float`-Wert zugewiesen wird.

Die Schrittweite 1 kann man sich bei `range()` übrigens sparen, dass ist bereits der Default-Wert.

Man könnte die einzelnen Arbeitsschritte dann noch in Funktionen stecken, damit auf Moduleben am Ende nicht alle möglichen Zwischenwerte existieren, die man überhaupt gar nicht mehr benötigt. Ein typisches Idiom für eine Hauptfunktion ist in Python:

Code: Alles auswählen

def main():
    # Hier kommt das Hauptprogramm...


if __name__ == '__main__':
    main()
Jetzt läuft die `main()`-Funktion nur wenn das Modul als Programm ausgeführt wird, aber nicht wenn man es nur importiert. So kann man beispielsweise in einer Python-Shell die Funktionen einzeln testen und ausprobieren.

Die Sonderbehandlung mit ``j == 0`` in der letzten Schleife kann man bestimmt eleganter Ausdrücken, so dass den Rechenausdruck nur einmal schreiben muss.

Edit: Ungetestet, dafür Python und keine furchtbaren Einbuchstaben-Namen:

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


def main():
    with open('a1.txt') as lines:
        messwerte = [list(map(float, line.split())) for line in lines]
    # 
    # Kalibrierfunktion einlesen.
    # 
    grad = int(input('Bitte geben Sie den Grad des Kalibrierpolynoms ein: '))

    print('Geben Sie nun die Koeffizienten absteigend an!')
    koeffizienten = [
        float(input('Koeffizient {0}:'.format(i)))
        for i in reversed(range(0, grad + 1))
    ]
    # 
    # Umrechnen der Spannungen in eine Geschwindigkeit.
    # 
    for row in messwerte:
        wert = row[1]**grad * koeffizienten[0]
        for i, koeffizient in enumerate(koeffizienten, 1):
            wert += wert**(grad - i) * koeffizient
        row[1] = wert


if __name__ == '__main__':
    main()
scoobydo
User
Beiträge: 5
Registriert: Sonntag 17. Februar 2013, 16:55

Ok noch einmal vielen Dank!
Werde mal versuchen mich da durchzubeißen und in Zukunft die Indizes zu minimieren.
Antworten