diff --git a/03-numpy-und-matplotlib/folien-code/folien-code.ipynb b/03-numpy-und-matplotlib/folien-code/folien-code.ipynb
index 0d69cf7377d7a679581b62e7e21ac7be2b244e9e..c911ae61890044918619be0794013ebeaa2638bf 100644
--- a/03-numpy-und-matplotlib/folien-code/folien-code.ipynb
+++ b/03-numpy-und-matplotlib/folien-code/folien-code.ipynb
@@ -339,8 +339,8 @@
     "from numpy.polynomial import Polynomial\n",
     "\n",
     "x = np.arange(10)\n",
-    "y = 2 * x\n",
-    "# y = x ** 2\n",
+    "y = 2 * x + 1\n",
+    "# y = x ** 2 + 1\n",
     "\n",
     "p = Polynomial.fit(x, y, deg=1).convert()\n",
     "\n",
@@ -361,7 +361,7 @@
     "from sklearn.linear_model import LinearRegression\n",
     "\n",
     "x = np.arange(10).reshape(-1, 1)\n",
-    "y = x ** 2\n",
+    "y = x ** 2 + 1\n",
     "\n",
     "linreg = LinearRegression()\n",
     "linreg.fit(x, y)\n",
@@ -379,7 +379,7 @@
    "source": [
     "\n",
     "x = np.arange(10).reshape(-1, 1)\n",
-    "y = x ** 2\n",
+    "y = x ** 2 + 1\n",
     "\n",
     "x_poly = np.hstack((x, x**2)) # shape: 10 x 2\n",
     "\n",
diff --git a/03-numpy-und-matplotlib/folien-code/folien-code.py b/03-numpy-und-matplotlib/folien-code/folien-code.py
index 303c74a9bf04b1cf85923aca7dfe1f529aa39ab6..cbec4e0b37903dc0fc345426864329d7e5a6df72 100644
--- a/03-numpy-und-matplotlib/folien-code/folien-code.py
+++ b/03-numpy-und-matplotlib/folien-code/folien-code.py
@@ -224,8 +224,8 @@ ax = plt.gca()
 from numpy.polynomial import Polynomial
 
 x = np.arange(10)
-y = 2 * x
-# y = x ** 2
+y = 2 * x + 1
+# y = x ** 2 + 1
 
 p = Polynomial.fit(x, y, deg=1).convert()
 
@@ -240,7 +240,7 @@ plt.scatter(x, y, color='r')
 from sklearn.linear_model import LinearRegression
 
 x = np.arange(10).reshape(-1, 1)
-y = x ** 2
+y = x ** 2 + 1
 
 linreg = LinearRegression()
 linreg.fit(x, y)
@@ -252,7 +252,7 @@ print(linreg.intercept_, linreg.coef_)
 # %% Lineare Regression mit Scikit-Learn, Grad 2
 
 x = np.arange(10).reshape(-1, 1)
-y = x ** 2
+y = x ** 2 + 1
 
 x_poly = np.hstack((x, x**2)) # shape: 10 x 2
 
diff --git a/03-numpy-und-matplotlib/solutions/folien-code/folien-code.ipynb b/03-numpy-und-matplotlib/solutions/folien-code/folien-code.ipynb
index 0d69cf7377d7a679581b62e7e21ac7be2b244e9e..c911ae61890044918619be0794013ebeaa2638bf 100644
--- a/03-numpy-und-matplotlib/solutions/folien-code/folien-code.ipynb
+++ b/03-numpy-und-matplotlib/solutions/folien-code/folien-code.ipynb
@@ -339,8 +339,8 @@
     "from numpy.polynomial import Polynomial\n",
     "\n",
     "x = np.arange(10)\n",
-    "y = 2 * x\n",
-    "# y = x ** 2\n",
+    "y = 2 * x + 1\n",
+    "# y = x ** 2 + 1\n",
     "\n",
     "p = Polynomial.fit(x, y, deg=1).convert()\n",
     "\n",
@@ -361,7 +361,7 @@
     "from sklearn.linear_model import LinearRegression\n",
     "\n",
     "x = np.arange(10).reshape(-1, 1)\n",
-    "y = x ** 2\n",
+    "y = x ** 2 + 1\n",
     "\n",
     "linreg = LinearRegression()\n",
     "linreg.fit(x, y)\n",
@@ -379,7 +379,7 @@
    "source": [
     "\n",
     "x = np.arange(10).reshape(-1, 1)\n",
-    "y = x ** 2\n",
+    "y = x ** 2 + 1\n",
     "\n",
     "x_poly = np.hstack((x, x**2)) # shape: 10 x 2\n",
     "\n",
diff --git a/03-numpy-und-matplotlib/solutions/folien-code/folien-code.py b/03-numpy-und-matplotlib/solutions/folien-code/folien-code.py
index 303c74a9bf04b1cf85923aca7dfe1f529aa39ab6..cbec4e0b37903dc0fc345426864329d7e5a6df72 100644
--- a/03-numpy-und-matplotlib/solutions/folien-code/folien-code.py
+++ b/03-numpy-und-matplotlib/solutions/folien-code/folien-code.py
@@ -224,8 +224,8 @@ ax = plt.gca()
 from numpy.polynomial import Polynomial
 
 x = np.arange(10)
-y = 2 * x
-# y = x ** 2
+y = 2 * x + 1
+# y = x ** 2 + 1
 
 p = Polynomial.fit(x, y, deg=1).convert()
 
@@ -240,7 +240,7 @@ plt.scatter(x, y, color='r')
 from sklearn.linear_model import LinearRegression
 
 x = np.arange(10).reshape(-1, 1)
-y = x ** 2
+y = x ** 2 + 1
 
 linreg = LinearRegression()
 linreg.fit(x, y)
@@ -252,7 +252,7 @@ print(linreg.intercept_, linreg.coef_)
 # %% Lineare Regression mit Scikit-Learn, Grad 2
 
 x = np.arange(10).reshape(-1, 1)
-y = x ** 2
+y = x ** 2 + 1
 
 x_poly = np.hstack((x, x**2)) # shape: 10 x 2
 
diff --git a/04-pandas-und-seaborn/03-odoo-eval.ipynb b/04-pandas-und-seaborn/03-odoo-eval.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..e0b9ad69aad0300d4eba7f952f27357fee9add1a
--- /dev/null
+++ b/04-pandas-und-seaborn/03-odoo-eval.ipynb
@@ -0,0 +1,52 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Odoo Datenanalyse\n",
+    "\n",
+    "Odoo ist ein ERP-System, ähnlich wie SAP, aber Open-Source. Man kann\n",
+    "damit u. a. Verkaufsaufträge und Rechnungen aufzeichen. Anbei befindet\n",
+    "sich die Datei `odoo-data.xlsx`, die Nils Fürkotter in der Lernfabrik\n",
+    "aufgezeichnet hat. Ihre Aufgabe besteht nun darin, die Daten zu\n",
+    "analysieren.\n",
+    "\n",
+    "-   Lesen Sie die Daten mit Pandas ein und geben Sie die Anzahl der\n",
+    "    Aufträge aus.\n",
+    "-   Erstellen Sie dann ein Pie-Chart, das das Verhältnis der Aufträge\n",
+    "    von Einzelpersonen und Unternehmen zeigt. Die gezeigte Information\n",
+    "    wäre z. B. Aufträge stammen zu 80 % von Einzelpersonen und 20 % von\n",
+    "    Unternehmen.\n",
+    "-   Erstellen Sie ein Barplot, das den Umsatz nach Kundentypen zeigt.\n",
+    "    Die gezeigte Information wäre z. B. Einzelpersonen haben 180 000 €\n",
+    "    Umsatz und Unternehmen 220 000 € Umsatz erwirtschaftet.\n",
+    "-   Erstellen Sie ein Histogramm, das die Verteilung der Umsätze pro\n",
+    "    Auftrag nach Kundentypen zeigt. Die gezeigte Information wäre z. B.\n",
+    "    Aufträge von Einzelpersonen haben Umsätze zwischen 50 € und 150 €\n",
+    "    und Aufträge von Unternehmen haben hauptsächlich Umsätze zwischen\n",
+    "    400 € und 600 €.\n",
+    "\n",
+    "Hier Ihr Start-Code:"
+   ],
+   "id": "0003-ffd65dfc8cad6b993d607936d89fb4de4d542de8348b893e161b721771f"
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "style": "python"
+   },
+   "outputs": [],
+   "source": [
+    "import pandas as pd\n",
+    "import seaborn as sns\n",
+    "import matplotlib.pyplot as plt\n"
+   ],
+   "id": "0004-d7e9dfa1635b2f39c536f959558e13284c1b5a3e2118f74285f499be56b"
+  }
+ ],
+ "nbformat": 4,
+ "nbformat_minor": 5,
+ "metadata": {}
+}
diff --git a/04-pandas-und-seaborn/odoo-data.xlsx b/04-pandas-und-seaborn/odoo-data.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..fb7496a8ba81929b5b15abdba89f01b9bfb1209f
Binary files /dev/null and b/04-pandas-und-seaborn/odoo-data.xlsx differ
diff --git a/04-pandas-und-seaborn/solutions/03-odoo-eval-sol.ipynb b/04-pandas-und-seaborn/solutions/03-odoo-eval-sol.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..a7441787671ac3b72cd721f275d246bd3f13f5e4
--- /dev/null
+++ b/04-pandas-und-seaborn/solutions/03-odoo-eval-sol.ipynb
@@ -0,0 +1,320 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Odoo Datenanalyse\n",
+    "\n",
+    "Odoo ist ein ERP-System, ähnlich wie SAP, aber Open-Source. Man kann\n",
+    "damit u. a. Verkaufsaufträge und Rechnungen aufzeichen. Anbei befindet\n",
+    "sich die Datei `odoo-data.xlsx`, die Nils Fürkotter in der Lernfabrik\n",
+    "aufgezeichnet hat. Ihre Aufgabe besteht nun darin, die Daten zu\n",
+    "analysieren.\n",
+    "\n",
+    "-   Lesen Sie die Daten mit Pandas ein und geben Sie die Anzahl der\n",
+    "    Aufträge aus.\n",
+    "-   Erstellen Sie dann ein Pie-Chart, das das Verhältnis der Aufträge\n",
+    "    von Einzelpersonen und Unternehmen zeigt. Die gezeigte Information\n",
+    "    wäre z. B. Aufträge stammen zu 80 % von Einzelpersonen und 20 % von\n",
+    "    Unternehmen.\n",
+    "-   Erstellen Sie ein Barplot, das den Umsatz nach Kundentypen zeigt.\n",
+    "    Die gezeigte Information wäre z. B. Einzelpersonen haben 180 000 €\n",
+    "    Umsatz und Unternehmen 220 000 € Umsatz erwirtschaftet.\n",
+    "-   Erstellen Sie ein Histogramm, das die Verteilung der Umsätze pro\n",
+    "    Auftrag nach Kundentypen zeigt. Die gezeigte Information wäre z. B.\n",
+    "    Aufträge von Einzelpersonen haben Umsätze zwischen 50 € und 150 €\n",
+    "    und Aufträge von Unternehmen haben hauptsächlich Umsätze zwischen\n",
+    "    400 € und 600 €.\n",
+    "\n",
+    "## Lösung\n",
+    "\n",
+    "Zunächst lesen wir den Datensatz mit der `pd.read_excel`-Funktion ein.\n",
+    "Dafür brauchen wir die Bibliothek `openpyxl`, die hoffentlich schon\n",
+    "installiert ist. Wenn nicht, können Sie sie mit\n",
+    "`mamba install -n ml openpyxl`, wobei ml der Umgebungsname ist,\n",
+    "installieren."
+   ],
+   "id": "0004-a0964a79c2d2ab0a6c2663854450e826b2d478a719d1ccce6497bd64d94"
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "style": "python"
+   },
+   "outputs": [],
+   "source": [
+    "import pandas as pd\n",
+    "import seaborn as sns\n",
+    "import matplotlib.pyplot as plt\n",
+    "\n",
+    "data = pd.read_excel('odoo-data.xlsx')"
+   ],
+   "id": "0005-237116bae51d87da8bfac1efb32ed96a4ac71d6d1471d771fd9cac013be"
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Wir geben als erstes aus, wie viele Aufträge es insgesamt gibt:"
+   ],
+   "id": "0006-0278cc28842eeecc0cc1259b2a4462d0297fd9356560e647f9aa67086db"
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [
+    {
+     "output_type": "stream",
+     "name": "stdout",
+     "text": [
+      "Anzahl Aufträge: 2125"
+     ]
+    }
+   ],
+   "source": [
+    "print('Anzahl Aufträge:', len(data))"
+   ],
+   "id": "0007-053cc9903c4f934e49bcf5d0b964e9337c1e648638fe1add2750f64b60a"
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Um konsistente Farben zu verwenden, definieren wir ein Dictionary mit\n",
+    "den Farben für die einzelnen Typen:"
+   ],
+   "id": "0008-ca4c12ba31cd853b088a12bc7f68a4677950a43a37a6d5211367b4b9865"
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "style": "python"
+   },
+   "outputs": [],
+   "source": [
+    "colors = {'Einzelperson': 'tab:blue', 'Unternehmen': 'tab:orange'}"
+   ],
+   "id": "0009-8866ed2619e427a57a38cc1f9b3d2b949a9ca6cf4664473b93a4535a2b9"
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Pie-Chart der Kundentypen\n",
+    "\n",
+    "Um den ersten Plot zu erstellen, zählen wir zunächst wie viele Aufträge\n",
+    "es von Einzelpersonen und wie viele von Unternehmen gibt. Das geht mit\n",
+    "`value_counts()`."
+   ],
+   "id": "0011-ca0de42f0ea048138e772acfa78e19b9efa23c3562cc54337fbed35d948"
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "style": "python"
+   },
+   "outputs": [],
+   "source": [
+    "customer_type = data['Kunde/Unternehmenstyp']\n",
+    "counts_type = customer_type.value_counts()\n",
+    "counts_type.name = ''                         # remove ylabel\n",
+    "counts_type = counts_type.loc[colors.keys()]  # reorder according to colors"
+   ],
+   "id": "0012-2e2b4c17c6c1914754697469e5df2e5ed4923552c5d075c1a209f37e957"
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Jetzt plotten wir das Verhältnis der Aufträge als Pie-Chart. Dabei\n",
+    "verwenden wir die `plot.pie`-Methode von Pandas. Wir geben die Farben\n",
+    "aus dem Dictionary an und formatieren den Text mit\n",
+    "`autopct='{:.1f}%'.format`. Das Ergebnis sieht so aus:"
+   ],
+   "id": "0013-d98f7f54a6505b26cd1458026fd8ea83e5cea6361390fad9b271543f38d"
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "style": "python"
+   },
+   "outputs": [],
+   "source": [
+    "counts_type.plot.pie(colors=colors.values(), autopct='{:.1f}%'.format, startangle=-50)\n",
+    "plt.title('Verhältnis der Aufträge')"
+   ],
+   "id": "0014-a3ad3be8323d84a1e594eec4878583ba4e4e2c7c8df2e93cfda1d9ddfa6"
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Alternativ können wir auch die `plt.pie`-Funktion von Matplotlib\n",
+    "verwenden, was sehr ähnlich funktioniert.:"
+   ],
+   "id": "0015-7bec95538841de435f5b289e1c8564c1c607dab31493448208f7c5bbad7"
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "style": "python"
+   },
+   "outputs": [],
+   "source": [
+    "plt.pie(counts_type, labels=counts_type.index, colors=colors.values(), autopct='%1.1f%%', startangle=-50)\n",
+    "plt.title('Verhältnis der Aufträge')"
+   ],
+   "id": "0016-f30c65e85874b1995aa6f489fe1a2fc3052368a2f1a850391115ca50c4f"
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Seaborn bietet keine Funktion für Pie-Charts an.\n",
+    "\n",
+    "### Barplot des Umsatzes nach Kundentypen\n",
+    "\n",
+    "Um den Gesamtumsatz nach Kundentypen zu ermitteln, verwenden wir die\n",
+    "`groupby`-Methode von Pandas. Wir gruppieren die Daten nach dem Typ und\n",
+    "summieren den Umsatz. Das Ergebnis ist ein DataFrame mit den Typen als\n",
+    "Index und dem Umsatz als Spalte. `squeeze()` entfernt die Dimension des\n",
+    "Umsatzes, sodass wir nur eine Serie erhalten. Wir sortieren die Serie\n",
+    "nach den Farben, die wir vorher definiert haben:"
+   ],
+   "id": "0019-83fa942651ce7359d891283f57a14731131ef572ab2370651ae46b1e68c"
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "style": "python"
+   },
+   "outputs": [],
+   "source": [
+    "fig, ax = plt.subplots()\n",
+    "revenue = data.groupby('Kunde/Unternehmenstyp')['Gesamt'].sum().squeeze()\n",
+    "revenue = revenue.loc[colors.keys()]                            # reorder according to colors\n",
+    "ax = revenue.plot.bar(color=colors.values(), ax=ax)             # pandas\n",
+    "# ax.bar(revenue.index, revenue.values, color=colors.values())  # matplotlib\n",
+    "ax.set_ylabel('Gesamt')"
+   ],
+   "id": "0020-26b591c8cf51de10bd0fa8dec08f9c436b339118450dc55b06c94a74d5b"
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Seaborn gruppiert die Daten automatisch, wenn wir den `hue`-Parameter\n",
+    "verwenden. Wir müssen den `estimator`-Parameter verwenden, um den Umsatz\n",
+    "zu summieren, anstatt ihn zu mitteln. Der `errorbar`-Parameter gibt an,\n",
+    "dass wir keine Fehlerbalken wollen:"
+   ],
+   "id": "0021-fdb7ce41317da01fbbfde885ca952f363ed45258b194ed2eeff4c91fb6c"
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "style": "python"
+   },
+   "outputs": [],
+   "source": [
+    "sns.barplot(data, y='Gesamt', ax=ax, hue='Kunde/Unternehmenstyp', estimator=sum, errorbar=('ci', 0))"
+   ],
+   "id": "0022-eeb27de0b7169395daa59a03cbf2ca3ebe15c9b171d2d714275eb90797b"
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Histogramm des Umsatzes nach Kundentypen\n",
+    "\n",
+    "Um die Verteilung der Umsätze nach Kundentypen zu sehen, verwenden wir\n",
+    "die `hist`- oder die `plot.hist`-Methode von Pandas. Wir geben den\n",
+    "Spaltennamen und den Typ an. Es lassen sich keine Farben für die\n",
+    "Subplots angeben, daher müssen wir die Farben nachträglich setzen:"
+   ],
+   "id": "0024-22e27ab1072962a64c19aaadd088e368b3417dea6a5abe091bfdda7819f"
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "style": "python"
+   },
+   "outputs": [],
+   "source": [
+    "axs = data.hist(column='Gesamt', by='Kunde/Unternehmenstyp')   # (1 x 2)\n",
+    "# axs = data.plot.hist(column='Gesamt', by='Kunde/Unternehmenstyp', sharex=True, legend=False)  # (2 x 1)\n",
+    "# set colors afterwards\n",
+    "for ax in axs.flatten():\n",
+    "    c = colors[ax.get_title()]\n",
+    "    for p in ax.containers[0].patches:\n",
+    "        p.set_facecolor(c)"
+   ],
+   "id": "0025-d877bcd761d1ca32d4208be9b71b27099b82be96f1d8c21909e09c53c75"
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Alternativ können wir auch die `plt.hist`-Funktion von Matplotlib\n",
+    "verwenden. Wir erstellen ein Subplot mit 1 Zeile und 2 Spalten. Dann\n",
+    "iterieren wir über die Gruppen und erstellen für jede Gruppe ein\n",
+    "Histogramm. Wir setzen den Titel, die x-Achse und die y-Achse:"
+   ],
+   "id": "0026-5bc587277f2b73b50a2b848aade7245e9c90296fb933136d61e247ced3a"
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "style": "python"
+   },
+   "outputs": [],
+   "source": [
+    "fig, axs = plt.subplots(1, 2, constrained_layout=True, figsize=(10, 5))\n",
+    "for i, (ctype, v) in enumerate(data.groupby('Kunde/Unternehmenstyp')):\n",
+    "    axs[i].hist(v['Gesamt'], color=colors[ctype])\n",
+    "    axs[i].set_title(ctype)\n",
+    "    axs[i].set_xlabel('Gesamt')\n",
+    "    if i == 0:\n",
+    "        axs[i].set_ylabel('Anzahl Aufträge')"
+   ],
+   "id": "0027-7d2078d752036f9cbd6a6073f3eaa0d1c2459f8372609f608ee4f6f963a"
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "In Seaborn gibt es die `countplot`-Funktion, die die Anzahl der Aufträge\n",
+    "nach Typen zählt. Wir geben den `hue`-Parameter an, um die Farben zu\n",
+    "setzen. Der `alpha`-Parameter gibt die Transparenz an, weil die\n",
+    "Histogramme in einem Plot übereinander liegen:"
+   ],
+   "id": "0028-bf127cd3ed81d394e946710a54e2ff63a4b7e004c30069e97081efe6411"
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "style": "python"
+   },
+   "outputs": [],
+   "source": [
+    "sns.countplot(data=data, x='Gesamt', hue='Kunde/Unternehmenstyp', palette=colors, alpha=0.7, formatter='{:.0f}'.format)"
+   ],
+   "id": "0029-9d85047be203d22387fe72feaa244c59630adc4cb143c0fcff1e62a1df0"
+  }
+ ],
+ "nbformat": 4,
+ "nbformat_minor": 5,
+ "metadata": {}
+}
diff --git a/04-pandas-und-seaborn/solutions/odoo-data.xlsx b/04-pandas-und-seaborn/solutions/odoo-data.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..fb7496a8ba81929b5b15abdba89f01b9bfb1209f
Binary files /dev/null and b/04-pandas-und-seaborn/solutions/odoo-data.xlsx differ