{ "cells": [ { "cell_type": "markdown", "id": "21a11be0", "metadata": {}, "source": [ "# Lektion 2. Messtabellen:\n", "\n", "\n", "\n", "\n", "\n", "## Messtabellen in Python:\n", "\n", "Damit uns eine Programmiersprache wie Python Arbeit abnehmen kann, sollte es auch möglich sein, größere Datenmengen, wie z.B. die Werte einer Messtabelle, in einer Variablen zu speichern. Python bietet hierfür verschiedene Konzepte an. Jedes dieser Konzepte hat unterschiedliche Stärken und Schwächen. Die gängigsten Methoden sind list, tuple, bzw. sogenannte numpy.arrays und pandas.dataframes. Aufgrund der limitierten Zeit im PGP 1 werden wir uns hier lediglich mit zwei dieser vier Methoden auseinandersetzen. \n", "\n", "Fangen wir zunächst mit Listen an. Eine Liste ist eine Ansammlung von Werten, welche alle den gleichen oder ganz unterschiedliche Datentypen haben können. Eine Liste kann auf zwei unterschiedliche Art und Weisen erstellt werden:\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "ec6c1c02", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Wert1', 'Wert2', 'Wert3']" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Messwerte1 = ['Wert1', 'Wert2', 'Wert3'] # Variante 1\n", "Messwerte1" ] }, { "cell_type": "code", "execution_count": 3, "id": "21773a54", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 0.9, '1']" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Messwerte2 = list([2, 0.9, '1']) # Variante 2\n", "Messwerte2" ] }, { "cell_type": "markdown", "id": "be844385", "metadata": {}, "source": [ "Sobald wir eine liste erstellt haben, können wir eine ganze Reihe von unterschiedlichen Manipulationen durchführen, um sie nach unserem Belieben zu verändern.\n", "\n", "Wir können zum Beispiel die bestehende Liste um einen Wert erweitern (`append`) oder einen zusätzlichen Wert an eine beliebige Stelle in der Liste hinzufügen (`insert`)." ] }, { "cell_type": "code", "execution_count": 4, "id": "b8e22f05", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Wert1', 'Wert2', 'Wert3', 'Wert5']" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Messwerte1.append('Wert5')\n", "Messwerte1" ] }, { "cell_type": "code", "execution_count": 5, "id": "9bdd72bf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Wert1', 'Wert2', 'Wert3', 'Wert5', 'Wert4']" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Messwerte1.insert(4, 'Wert4')\n", "Messwerte1" ] }, { "cell_type": "markdown", "id": "8f7316a2", "metadata": {}, "source": [ "Ups, was ist denn in der letzten Zelle passiert? Wert4 wurde ja garnicht an Stelle 4 der Liste gesetzt, Python scheint nicht zählen zu können... \n", "\n", "Leider zählt Python doch richtig. In Python läuft der Index von Objekten in einer Liste immer von 0,1,2,3...n. Dies können wir auch ganz einfach überprüfen, indem wir unsere Liste in verschiedene \"Scheiben\" schneiden (so genanntes slicing). Dies geht wie folgt:" ] }, { "cell_type": "code", "execution_count": 6, "id": "83e9b6f0", "metadata": {}, "outputs": [], "source": [ "NeueWerte = ['Wert1', 'Wert2', 'Wert3', 'Wert4', 'Wert5', 'Wert6'] " ] }, { "cell_type": "markdown", "id": "173ccfee", "metadata": {}, "source": [ "Die kleinste Scheibe, welche wir abschneiden können, ist ein einzelner Wert:" ] }, { "cell_type": "code", "execution_count": 7, "id": "0b6c1f61", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Wert1'" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "NeueWerte[0] # Hier sehen Sie, dass der erste Wert den Index 0 hat." ] }, { "cell_type": "code", "execution_count": 8, "id": "c851e5b0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Wert3'" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wert_index_2 = NeueWerte[2] \n", "wert_index_2" ] }, { "cell_type": "markdown", "id": "7b9e07f7", "metadata": {}, "source": [ "Wie bei einer Pizza können wir uns natürlich auch größere Stücke nehmen." ] }, { "cell_type": "code", "execution_count": 9, "id": "a35f8d4a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Wert1', 'Wert2', 'Wert3']" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "NeueWerte[0:3]" ] }, { "cell_type": "code", "execution_count": 10, "id": "9e63410f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Wert3', 'Wert4', 'Wert5']" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "NeueWerte[2:5] # Python behandelt den letzten Wert wie in einem offenen Intervall [2,5)" ] }, { "cell_type": "code", "execution_count": 11, "id": "27ae7119", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Wert3', 'Wert4', 'Wert5', 'Wert6']" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "NeueWerte[2:] # Hier werden alle Werte mit dem Index >= 2 zurückgegeben" ] }, { "cell_type": "code", "execution_count": 12, "id": "bfb5a049", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Wert4', 'Wert5', 'Wert6']" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "NeueWerte[-3:] # Mit negativen Zahlen fangen Sie vom Ende der Liste an" ] }, { "cell_type": "markdown", "id": "0735b414", "metadata": {}, "source": [ "Neben `insert`, `append` und `slicing` bietet Python noch ein paar weitere Listenmanipulationen an. Mit Hilfe des `+` Operators können Sie die Werte in einer Liste direkt an eine andere Liste anfügen." ] }, { "cell_type": "code", "execution_count": 14, "id": "38098cd2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Wert1',\n", " 'Wert2',\n", " 'Wert3',\n", " 'Wert5',\n", " 'Wert4',\n", " 'Wert1',\n", " 'Wert2',\n", " 'Wert3',\n", " 'Wert4',\n", " 'Wert5',\n", " 'Wert6']" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Messwerte1 + NeueWerte" ] }, { "cell_type": "markdown", "id": "88ce1ac5", "metadata": {}, "source": [ "Anders als `append`, welches die zweite Liste als Ganzes an die erste Liste anfügt:" ] }, { "cell_type": "code", "execution_count": 15, "id": "e0d648ac", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Wert1',\n", " 'Wert2',\n", " 'Wert3',\n", " 'Wert5',\n", " 'Wert4',\n", " ['Wert1', 'Wert2', 'Wert3', 'Wert4', 'Wert5', 'Wert6']]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Messwerte1.append(NeueWerte)\n", "Messwerte1" ] }, { "cell_type": "markdown", "id": "24c36d81", "metadata": {}, "source": [ "Aber aufgepasst, bei `append` wird die Liste, an welche Sie die Daten anhängen (hier Messwerte1), direkt geändert (dies gilt auch für `insert`), während Sie beim `+` Operator die Variable überschreiben müssen, damit die Änderung wirksam wird. " ] }, { "cell_type": "code", "execution_count": 16, "id": "7763f952", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Wert1',\n", " 'Wert2',\n", " 'Wert3',\n", " 'Wert5',\n", " 'Wert4',\n", " ['Wert1', 'Wert2', 'Wert3', 'Wert4', 'Wert5', 'Wert6'],\n", " 'Wert1',\n", " 'Wert2',\n", " 'Wert3',\n", " 'Wert4',\n", " 'Wert5',\n", " 'Wert6']" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Messwerte1 = Messwerte1 + NeueWerte\n", "# Tipp: Dies können Sie auch einfach mithilfe von\n", "# Messwerte1 += NeueWerte\n", "Messwerte1" ] }, { "cell_type": "markdown", "id": "c9e1ed86", "metadata": {}, "source": [ "Zwei weitere nützliche Befehle im Zusammenhang von Listen ist die `len`- und `range`-Funktion. \n", "\n", "`len` gibt die Länge einer Liste zurück " ] }, { "cell_type": "code", "execution_count": 17, "id": "42f10cd5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['Wert1', 'Wert2', 'Wert3', 'Wert5', 'Wert4', ['Wert1', 'Wert2', 'Wert3', 'Wert4', 'Wert5', 'Wert6'], 'Wert1', 'Wert2', 'Wert3', 'Wert4', 'Wert5', 'Wert6']\n" ] }, { "data": { "text/plain": [ "12" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(Messwerte1)\n", "len(Messwerte1)" ] }, { "cell_type": "markdown", "id": "6858a55f", "metadata": {}, "source": [ "`range` erstellt ganzzahlige Werte zwischen zwei ganzen Zahlen" ] }, { "cell_type": "code", "execution_count": 18, "id": "49eaf0a3", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "range(0, 5, 2)" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "range(0, # <-- Startwert\n", " 5, # <-- Endwert (nicht mehr enthalten, offenes Ende)\n", " 2 # <-- Schrittweite\n", " )" ] }, { "cell_type": "markdown", "id": "fe1650e7", "metadata": {}, "source": [ "Sie können die `range` Rückgabe auch wieder in eine Liste umwandeln" ] }, { "cell_type": "code", "execution_count": 21, "id": "16670845", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 2, 4]" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(range(0,5,2))" ] }, { "cell_type": "markdown", "id": "7cd394f4", "metadata": {}, "source": [ "
\n", " \n", "#### Aufgabe 4.a.: Erstellen von Messwerttabellen:\n", "\n", "Erstellen Sie für jede Spalte der nachfolgenden Messtabelle eine Liste, welche die Messdaten beinhaltet. Benutzen Sie anschließend den `append` Befehl, um die Daten jeder Spalte an eine weitere Liste namens *daten* anzuhängen. \n", "\n", "| Messwertnummer | Spannung [V] | Strom [mA] | Fehler der Spannung [V] | Fehler des Stroms [mA] |\n", "|----------------|--------------|------------|-------------------------|---------------------------|\n", "| 1 | 12.00 | 110 | 0.32 | 10 |\n", "| 2 | 11.78 | 98 | 0.15 | 10 |\n", "| 3 | 12.56 | 102 | 0.63 | 10 |\n", "| 4 | 12.34 | 124 | 0.12 | 10 |\n", "| 5 | 12.01 | 105 | 0.20 | 10 |\n", "| 6 | 11.94 | 95 | 0.17 | 10 |\n", "\n", "\n", "Verwenden Sie anschließend das Slicing, um die umgesetzte Leistung im Widerstand für die Meswerte 3 und 5 zu berechnen.\n", "\n", "**Tipp:**\n", "\n", "1. Sie haben bereits die Funktionen für die Leistung in Aufgabe 3 definiert und können sie hier erneut verwenden. \n", "2. Das Slicen von verschachtelten Listen funktioniert genauso wie bei normalen Listen:\n", "\n", "```python\n", "spalte0 = daten[0] #<-- Wählt die Spalte 0 an \n", "spalte0[2] #<-- Wählt aus Spalte 0 den Messwert mit Index 2 an\n", "# oder als Einzeiler:\n", "daten[0][2] \n", "```\n", "\n", "3. Geben Sie an, wie sich die Messwertnummer zum Listenindex verhält.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "d85c9d1c", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "1f5981ff", "metadata": {}, "source": [ "## Arbeiten mit Messreihen:\n", "\n", "Bisher hat uns das programmieren eher mehr Arbeit gemacht als uns welche abgenommen. Zeitersparnis bekommen wir, wenn wir viele Rechnungen hintereinander ausführen müssen. Hierfür gibt es die **for**-Schleife. Diese Schleife führt die gleichen Zeilen eins Codes wiederholt für die Elemente in einer Liste aus:" ] }, { "cell_type": "code", "execution_count": 1, "id": "7c1708d8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Wert: 1\n", "Wert: 2\n", "Wert: 3\n", "Wert: 4\n", "Ergebnis: 6\n" ] } ], "source": [ "liste = [1, 2, 3, 4]\n", "\n", "for wert in liste:\n", " print('Wert:', wert)\n", " rechnung = wert + 2\n", "print('Ergebnis:', rechnung)" ] }, { "cell_type": "markdown", "id": "d5d5d551", "metadata": {}, "source": [ "Bei einer Schleife ist darauf zu achten, dass der Anweisungsblock, welcher wiederholt ausgeführt werden soll, mit 4x Leerzeichen eingrückt wurde. Dies entspricht einmal die **Tab-Taste**:\n", "\n", "\"Tab-Taste\"" ] }, { "cell_type": "code", "execution_count": null, "id": "950a88a9", "metadata": {}, "outputs": [], "source": [ "liste = [1, 2, 3, 4]\n", "print('Hier läuft das Hauptprogramm')\n", "\n", "for wert in liste:\n", " print('Schleife')\n", " print('Wert:', wert)\n", " rechnung = wert + 2\n", " \n", "print('Hier läuft wieder das Hauptprogramm')\n", "rechnung = rechnung + 5\n", "print('Letztes Ergebnis + 5: ', rechnung)" ] }, { "cell_type": "markdown", "id": "98c72ce5", "metadata": {}, "source": [ "Statt das Ergebnis lediglich per `print`-Anweisung darstellen zu lassen, können wir auch unser Wissen um Listen benutzen und die berechneten Werte einer neuen Liste anfügen:" ] }, { "cell_type": "code", "execution_count": 2, "id": "43275304", "metadata": {}, "outputs": [], "source": [ "# (Funktion haben wir bereits in der Vorbereitung definiert)\n", "def Spannung(Strom, Widerstand):\n", " '''\n", " Diese Funktion berechnet die Spannung eines Ohmschen \n", " Widerstands.\n", " \n", " Args:\n", " Strom (float): Der gemessene Strom in mA.\n", " Widerstand (float): Der Wert des verwendeten Widerstands\n", " in Ohm.\n", " \n", " Returns:\n", " float: Die berechnete Spannung in V.\n", " '''\n", " return Widerstand * Strom/1000" ] }, { "cell_type": "code", "execution_count": null, "id": "8a7692d4", "metadata": {}, "outputs": [], "source": [ "Stromwerte = [101, 105, 98, 87, 112] # mA\n", "Spannungswerte = [] # Einheit? <-- Deshalb Docstrings und Help!\n", "Widerstand = 100 # Ohm\n", "\n", "for Strom in Stromwerte:\n", " res = Spannung(Strom, Widerstand)\n", " Spannungswerte.append(res)\n", "\n", "Spannungswerte" ] }, { "cell_type": "markdown", "id": "c339e688", "metadata": {}, "source": [ "Python ermöglicht uns auch eine kompaktere Schreibweise, die so genannte \"list comprehension\": " ] }, { "cell_type": "code", "execution_count": null, "id": "96656272", "metadata": {}, "outputs": [], "source": [ "Spannungswerte = [Spannung(Strom, 100) for Strom in Stromwerte]\n", "Spannungswerte" ] }, { "cell_type": "markdown", "id": "c2870b72", "metadata": {}, "source": [ "Wir können auch über mehrere Daten gleichzeitig \"loopen\". Hierzu kann die `zip` Anweisung genutzt werden. `zip` verbindet hierbei die einzelnen Elemente einer Liste wie bei einem Reißverschluss miteinander:" ] }, { "cell_type": "code", "execution_count": null, "id": "51d82509", "metadata": {}, "outputs": [], "source": [ "Werte1 = ['A', 'B', 'C', 'D']\n", "Werte2 = [0, 1, 2, 3]\n", "\n", "for w1, w2 in zip(Werte1, Werte2):\n", " print(w1, ' und ', w2)" ] }, { "cell_type": "markdown", "id": "1ceaf5a6", "metadata": {}, "source": [ "Dies kann zum Beispiel dann hilfreich sein, wenn sich mehr als eine Variable ändern soll, z.B. bei einer Messreihe für die Schallgeschwindigkeit in Luft:" ] }, { "cell_type": "code", "execution_count": 4, "id": "af93a63c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[335.4904, 347.3442, 343.6145, 337.275, 331.6212, 342.0115, 336.2262]\n", "[335.4904, 347.3442, 343.6145, 337.275, 331.6212, 342.0115, 336.2262]\n" ] } ], "source": [ "# Gemessene Werte:\n", "frequenzen = [30.17, 30.63, 30.01, 29.98, 30.12, 29.87, 29.94] #kHz\n", "wellenlängen = [11.12, 11.34, 11.45, 11.25, 11.01, 11.45, 11.23] # mm\n", "\n", "# Variante 1:\n", "schallgeschindigkeiten = [] # m/s\n", "\n", "for f, l in zip(frequenzen, wellenlängen):\n", " schallgeschindigkeiten.append(f*l)\n", "\n", "print(schallgeschindigkeiten)\n", "\n", "# oder Variante 2:\n", "schallgeschindigkeiten2 = [f*l for f,l in zip(frequenzen, wellenlängen)]\n", "print(schallgeschindigkeiten2)" ] }, { "cell_type": "markdown", "id": "322e67e9", "metadata": {}, "source": [ "Wir können auch die `zip`-Anweisung mit mehr als nur zwei Listen verwenden:" ] }, { "cell_type": "code", "execution_count": 5, "id": "6c8d6f27", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a und 1 und x\n", "b und 2 und y\n", "c und 3 und z\n" ] } ], "source": [ "l1 = ['a', 'b', 'c']\n", "l2 = [1, 2, 3]\n", "l3 = ['x', 'y', 'z']\n", "\n", "for i,j,k in zip(l1, l2, l3):\n", " print(i, 'und', j, 'und', k)" ] }, { "cell_type": "markdown", "id": "0f1e9a18", "metadata": {}, "source": [ "
\n", " \n", "#### Aufgabe 4.b.: Werte berechnen:\n", "Kopieren Sie Ihre Lösung von Aufgabe 4.a. aus der Vorbereitung in das Notebook und berechnen Sie nun für die Messwerte aus Aufgabe 4 a. die Leistung $P$ und den Widerstand $R$ sowie deren Fehler. Nutzen Sie hierfür die ausführliche schrebweise der **for**-Schleife im Fall des Widerstands $R$ und den list-comprehension Syntax für die Leistung $P$. Fügen Sie die berechneten Werte als neue Spalten an die Liste *daten* an. \n", "
" ] }, { "cell_type": "code", "execution_count": 6, "id": "8a0add34", "metadata": {}, "outputs": [], "source": [ "# Hier eine kleine Hilfestellung für den Start:\n", "# Messwerttabelle aus Aufgabe 4. a.:\n", "messwert_nummer = list(range(1,7,1))\n", "spannungs_wert = [12., 11.78, 12.56, 12.34, 12.01, 11.94]\n", "strom_werte = [110, 98, 102, 124, 105, 95]\n", "dspannung_wetre = [0.32, 0.15, 0.63, 0.12, 0.20, 0.17]\n", "dstrom_werte = [10]*len(messwert_nummer)\n", "widerstand = []\n", "\n", "daten = [messwert_nummer, spannungs_wert, strom_werte, dspannung_wetre, dstrom_werte]\n", "\n", "# Beispiel für die Berechnung des Widerstandes:\n", "def res(i, u):\n", " r = u/i\n", " return r\n", "\n", "for strom, spannung in zip(daten[2], daten[1]):\n", " widerstand.append(res(strom, spannung))\n", " \n", "daten.append(widerstand)\n", "\n", "# Jetzt sind Sie gefragt:\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "id": "210f65ba", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.4" } }, "nbformat": 4, "nbformat_minor": 5 }