Skip to content
Snippets Groups Projects
Commit 6e2530ec authored by Christof Kaufmann's avatar Christof Kaufmann
Browse files

Notebooks from applied-cs/data-science@9c29683e

parent 38e33102
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id:0002-8585dc9b0ed930d72556df47900a3e3dae65ea2bd7f244d5822c3bb4206 tags: %% Cell type:markdown id:0002-2465e64373be0da127a2abebf7ac7f2bffb49524f9069ee09a7bf51c6fd tags:
# Feature-Map # Feature-Map
In dieser Aufgabe wollen wir die Features entsprechend der In dieser Aufgabe wollen wir die Features entsprechend der
Korrelationsmatrix auf einer Karte plotten. Korrelationsmatrix auf einer Karte plotten.
1. Laden Sie die Autodaten aus `autos.csv` als DataFrame. 1. Laden Sie die Autodaten aus `autos.csv` als DataFrame.
2. *Bonus: Werfen Sie die Ausreißer raus. Was hat das für Auswirkungen 2. *Bonus: Werfen Sie die Ausreißer raus. Was hat das für Auswirkungen
auf das Ergebnis.* auf das Ergebnis.*
3. Berechnen Sie die Korrelationsmatrix. 3. Berechnen Sie die Korrelationsmatrix.
4. Wandeln Sie die Korrelationsmatrix $P$ in eine Distanzmatrix 4. Wandeln Sie die Korrelationsmatrix $P$ in eine Distanzmatrix
$D = \sqrt{1 - P}$ um. \*Bonus: Probieren Sie auch $D = \sqrt{1 - P}$ um. *Bonus: Probieren Sie auch
$D = \sqrt{1 - |P|}$ $D = \sqrt{1 - |P|}$*
5. Finden Sie mit MDS die Koordinaten zu den Features. Sie benötigen 5. Finden Sie mit MDS die Koordinaten $X_p$ zu den Features. Sie
`dissimilarity='precomputed'`, damit Sie in `fit` $D$ reingeben benötigen bei der Initialisierung den Parameter
können. `dissimilarity='precomputed'`, damit Sie in `fit` bzw.
`fit_transform` $D$ (anstatt $X$) reingeben können.
6. Plotten Sie das Ergebnis mittels Plotly Express’ Scatter-Plot, denn 6. Plotten Sie das Ergebnis mittels Plotly Express’ Scatter-Plot, denn
da können Sie an das Argument `text` die Feature-Namen übergeben. da können Sie zusätzlich zu `data_frame=`$X_p$, `x=0` und `y=1` an
das Argument `text` die Feature-Namen übergeben.
%% Cell type:code id:0003-c1bb0a9ce1897e013bbc5224cd3031da808967b4ce5f467e752db79b3b6 tags: %% Cell type:code id:0003-c1bb0a9ce1897e013bbc5224cd3031da808967b4ce5f467e752db79b3b6 tags:
``` ```
import numpy as np import numpy as np
import pandas as pd import pandas as pd
import plotly.express as px import plotly.express as px
from sklearn.manifold import MDS from sklearn.manifold import MDS
``` ```
%% Cell type:markdown id:0005-2b2e02f7c099c0b3c2e7ee38e724334b181f374b2f6da5066b33d7489c5 tags: %% Cell type:markdown id:0005-2b2e02f7c099c0b3c2e7ee38e724334b181f374b2f6da5066b33d7489c5 tags:
## Lösung ## Lösung
Hier der Code zur Lösung: Hier der Code zur Lösung:
%% Cell type:code id:0006-472ff22b9cdec2be85fd14f451bb4cdea7db8ee3cbf28c128c994cf0453 tags: %% Cell type:code id:0006-472ff22b9cdec2be85fd14f451bb4cdea7db8ee3cbf28c128c994cf0453 tags:
``` ```
df = pd.read_csv('autos.csv').drop(columns=['Marke', 'Modell']) df = pd.read_csv('autos.csv').drop(columns=['Marke', 'Modell'])
# df = df[df.Grundpreis < 150_000] # mit Ausreißern ist der Grundpreis weit weg von den Motordaten # df = df[df.Grundpreis < 150_000] # mit Ausreißern ist der Grundpreis weit weg von den Motordaten
corr = df.corr() corr = df.corr()
dist_corr = np.sqrt(1 - corr) dist_corr = np.sqrt(1 - corr)
# dist_corr = np.sqrt(1 - np.abs(corr)) # mit abs rückt die Türanzahl näher an alle anderes # dist_corr = np.sqrt(1 - np.abs(corr)) # mit abs rückt die Türanzahl näher an alle anderes
mds = MDS(dissimilarity='precomputed', normalized_stress='auto') mds = MDS(dissimilarity='precomputed', normalized_stress='auto')
corr_map = mds.fit_transform(dist_corr) corr_map = mds.fit_transform(dist_corr)
corr_map = pd.DataFrame(corr_map) corr_map = pd.DataFrame(corr_map)
corr_map['feature'] = corr.columns corr_map['feature'] = corr.columns
``` ```
%% Cell type:markdown id:0007-96c5b071fc624449a3bff00f5acf449ff13a3986090c619ea3c40dbebf7 tags: %% Cell type:markdown id:0007-96c5b071fc624449a3bff00f5acf449ff13a3986090c619ea3c40dbebf7 tags:
Der Grundpreis ist ohne Ausreißer näher an den Motordaten, d.h. der Der Grundpreis ist ohne Ausreißer näher an den Motordaten, d.h. der
Preis verhält sich ähnlich. Mit Ausreißer ist der Preis weit weg. Das Preis verhält sich ähnlich. Mit Ausreißer ist der Preis weit weg. Das
lässt sich so interpretieren, dass der Preis für sehr teure Autos nicht lässt sich so interpretieren, dass der Preis für sehr teure Autos nicht
mehr im Verhältnis zum Motor steht. mehr im Verhältnis zum Motor steht.
%% Cell type:code id:0008-20ca1c79ef727fdf527b2a98d7d6fe563ef6fd9c2b005bb1fdfb364bbbb tags: %% Cell type:code id:0008-20ca1c79ef727fdf527b2a98d7d6fe563ef6fd9c2b005bb1fdfb364bbbb tags:
``` ```
px.scatter(corr_map, x=0, y=1, text=corr.columns) px.scatter(corr_map, x=0, y=1, text=corr.columns)
``` ```
......
%% Cell type:markdown id:0002-8585dc9b0ed930d72556df47900a3e3dae65ea2bd7f244d5822c3bb4206 tags: %% Cell type:markdown id:0002-2465e64373be0da127a2abebf7ac7f2bffb49524f9069ee09a7bf51c6fd tags:
# Feature-Map # Feature-Map
In dieser Aufgabe wollen wir die Features entsprechend der In dieser Aufgabe wollen wir die Features entsprechend der
Korrelationsmatrix auf einer Karte plotten. Korrelationsmatrix auf einer Karte plotten.
1. Laden Sie die Autodaten aus `autos.csv` als DataFrame. 1. Laden Sie die Autodaten aus `autos.csv` als DataFrame.
2. *Bonus: Werfen Sie die Ausreißer raus. Was hat das für Auswirkungen 2. *Bonus: Werfen Sie die Ausreißer raus. Was hat das für Auswirkungen
auf das Ergebnis.* auf das Ergebnis.*
3. Berechnen Sie die Korrelationsmatrix. 3. Berechnen Sie die Korrelationsmatrix.
4. Wandeln Sie die Korrelationsmatrix $P$ in eine Distanzmatrix 4. Wandeln Sie die Korrelationsmatrix $P$ in eine Distanzmatrix
$D = \sqrt{1 - P}$ um. \*Bonus: Probieren Sie auch $D = \sqrt{1 - P}$ um. *Bonus: Probieren Sie auch
$D = \sqrt{1 - |P|}$ $D = \sqrt{1 - |P|}$*
5. Finden Sie mit MDS die Koordinaten zu den Features. Sie benötigen 5. Finden Sie mit MDS die Koordinaten $X_p$ zu den Features. Sie
`dissimilarity='precomputed'`, damit Sie in `fit` $D$ reingeben benötigen bei der Initialisierung den Parameter
können. `dissimilarity='precomputed'`, damit Sie in `fit` bzw.
`fit_transform` $D$ (anstatt $X$) reingeben können.
6. Plotten Sie das Ergebnis mittels Plotly Express’ Scatter-Plot, denn 6. Plotten Sie das Ergebnis mittels Plotly Express’ Scatter-Plot, denn
da können Sie an das Argument `text` die Feature-Namen übergeben. da können Sie zusätzlich zu `data_frame=`$X_p$, `x=0` und `y=1` an
das Argument `text` die Feature-Namen übergeben.
%% Cell type:code id:0003-c1bb0a9ce1897e013bbc5224cd3031da808967b4ce5f467e752db79b3b6 tags: %% Cell type:code id:0003-c1bb0a9ce1897e013bbc5224cd3031da808967b4ce5f467e752db79b3b6 tags:
``` ```
import numpy as np import numpy as np
import pandas as pd import pandas as pd
import plotly.express as px import plotly.express as px
from sklearn.manifold import MDS from sklearn.manifold import MDS
``` ```
......
%% Cell type:markdown id:0001-9c88d904212173177e3cd805c405ca6bffb6c39ce47a88ff66351aa9536 tags: %% Cell type:markdown id:0001-d947a237f8749d5a07e6b16afc9277567861c9725260e81c2bffa0ec68d tags:
# MNIST visualisieren # MNIST visualisieren
In dieser Aufgabe wollen wir einen hochdimensionalen Datensatz in 2D In dieser Aufgabe wollen wir einen hochdimensionalen Datensatz in 2D
(oder 3D) plotten. Die Daten werden schon geladen. (oder 3D) plotten. Die Daten werden schon geladen und eine
Plotting-Funktion ist schon vorbereitet. *Hinweis: Der Code benötigt
einen Jupyter-Kontext, also Jupyter Lab oder VS Code mit interaktivem
Modus.*
%% Cell type:code id:0002-f9e5f87e267af56fbd5014863286132d368c2876d241287b849ceff60cc tags: %% Cell type:code id:0002-bbdfcc807a677cb51c1861eff7e69e8889bcc9c56d11ca63b972d0d11c7 tags:
``` ```
import io
import matplotlib.pyplot as plt
import numpy as np import numpy as np
import pandas as pd
import plotly.express as px import plotly.express as px
from plotly import graph_objects as go
from ipywidgets import VBox, Box, Image, Layout
from tensorflow.keras.datasets.mnist import load_data from tensorflow.keras.datasets.mnist import load_data
def interactive_scatter_plot(X_high, X_low, y):
"""
Make a scatter plot reacting on hover by showing the image
"""
assert X_high.shape[0] == X_low.shape[0] == y.shape[0], 'Arrays should have the same number of samples'
assert X_high.shape[1] > X_low.shape[1], 'First array should bei original images, second with reduced dimension'
x_name, y_name = 0, 1 if not isinstance(X_low, pd.DataFrame) else X_low.columns[:2]
scatter = px.scatter(X_low, x=x_name, y=y_name, color=y, hover_data={'idx': np.arange(len(X_low))})
scatter.update_xaxes(title_text=None)
scatter.update_yaxes(title_text=None)
# show image on hover
img = Image(format='png', width=56)
def update(trace, points, state):
# index relative to this trace (trace = color group)
trace_index = points.point_inds
if len(trace_index) == 0:
# this returns for traces not having the data point
return
# absolute indices of this trace
digit_indices = trace['customdata']
data_index = digit_indices[trace_index]
# convert image to PNG bytes and set image to it
rawBytes = io.BytesIO()
plt.imsave(rawBytes, X_high[data_index].reshape((28, 28)), format='png', cmap='gray')
rawBytes.seek(0)
img.value = rawBytes.read()
fig = go.FigureWidget(data=scatter.data, layout=scatter.layout)
# figure contains for each color a data trace and for each we have to define the on_hover function
for fig_data in fig.data:
fig_data.on_hover(update)
# layout of plot and centered image
return VBox([fig, Box([img], layout=Layout(display='flex', flex_flow='column', align_items='center'))])
# load data
(x_train, y_train), (x_test, y_test) = load_data() (x_train, y_train), (x_test, y_test) = load_data()
# reshape test set to 10 000 x 784 # reshape test set to 10 000 x 784
X = x_test.reshape(-1, 28 * 28) X = x_test.reshape(-1, 28 * 28)
``` ```
%% Cell type:markdown id:0003-fef1281e3edb72c906210479c5811c47fe2289914626b2c40534881280c tags: %% Cell type:markdown id:0003-8683c8202e9f2668b92e0aa78e49a38198e4d638b65ac30ec6020531315 tags:
Wenn Sie mögen ist hier ein Plot von verschiedenen Bildern der gleichen Wenn Sie mögen ist hier ein Plot von verschiedenen Bildern der gleichen
Klasse. So können Sie ein Blick reinwerfen. Klasse. So können Sie ein Blick in den Datensatz werfen.
%% Cell type:code id:0004-c879d58b500c83a0364d8680cc6b05c9cc97d36d3ea3743e112c56644db tags: %% Cell type:code id:0004-c879d58b500c83a0364d8680cc6b05c9cc97d36d3ea3743e112c56644db tags:
``` ```
# plot 50 examples for each digit # plot 50 examples for each digit
imgs = np.empty((50, 10, 28, 28)) imgs = np.empty((50, 10, 28, 28))
for j in range(10): for j in range(10):
imgs[:, j] = x_test[y_test == j][:50] imgs[:, j] = x_test[y_test == j][:50]
fig = px.imshow(imgs, animation_frame=0, facet_col=1, facet_col_wrap=5, binary_string=True) fig = px.imshow(imgs, animation_frame=0, facet_col=1, facet_col_wrap=5, binary_string=True)
fig.update_xaxes(showticklabels=False) fig.update_xaxes(showticklabels=False)
fig.update_yaxes(showticklabels=False) fig.update_yaxes(showticklabels=False)
fig.show() fig.show()
``` ```
%% Cell type:markdown id:0007-d262459c63ed3d98add57f2c48715daab6ff8a674c4e923ee87f87f61ad tags: %% Cell type:markdown id:0006-80f9722cacf3b6426928b4bbdb5fcb32d9d50cc0aaccb011c37c93b7f19 tags:
Transformieren Sie die Daten in 2D (ode 3D) und plotten die Transformieren Sie die Daten in 2D (ode 3D) und plotten die
Transformierten Daten als Scatter-Plot mit `y_test` als Transformierten Daten als Scatter-Plot mit `y_test` als
Farbunterscheidung. Farbunterscheidung. Für PCA ist es schon vorbereitet, aber probieren Sie
auch andere Techniken.
## Lösung
Hier der Code zur Lösung: *Hinweis: Falls Sie UMAP verwenden wollen und es nicht installiert ist,
installieren Sie es mit `mamba install umap-learn`. Sie können es dann
mit `from umap import UMAP` importieren und wie jedes andere
Scikit-Learn-Modell verwenden.*
%% Cell type:code id:0008-a04806d4df0812cf8fba0aa2e4e76d43ce0a2c8b2e2a9d7c032abc4e78f tags: %% Cell type:code id:0007-ae5f11cf01a3212244c7bf86638455d0d6a145258c3112beb4c12633405 tags:
``` ```
from umap import UMAP
from sklearn.decomposition import PCA from sklearn.decomposition import PCA
pca = PCA(n_components=2) pca = PCA(n_components=2)
X_pca = pca.fit_transform(X) X_pca = pca.fit_transform(X)
plot = interactive_scatter_plot(X, X_pca, y_test)
display(plot) # display from IPython.display implicitly in Jupyter imported, which is required anyway
```
%% Cell type:markdown id:0009-96b725bb9f2f51ff66328e5e9a5fc2dd4e69320f643fa34ea6db4da4c4a tags:
## Lösung
Hier der Code für UMAP:
%% Cell type:code id:0010-7e298e46cd6eb14f0920a2bed338fa02b756553adb499afb357944d32ae tags:
```
from umap import UMAP
umap = UMAP(n_neighbors=20, metric='manhattan', min_dist=0.1) umap = UMAP(n_neighbors=20, metric='manhattan', min_dist=0.1)
X_umap = umap.fit_transform(X) X_umap = umap.fit_transform(X)
scatter1 = px.scatter(X_pca, x=0, y=1, color=y_test) plot = interactive_scatter_plot(X, X_umap, y_test)
scatter1.show() display(plot) # display from IPython.display implicitly in Jupyter imported, which is required anyway
scatter2 = px.scatter(X_umap, x=0, y=1, color=y_test, hover_data={'class': y_test, 'index': np.arange(len(X_umap))})
scatter2.show()
``` ```
%% Cell type:markdown id:0009-96c5b071fc624449a3bff00f5acf449ff13a3986090c619ea3c40dbebf7 tags:
Der Grundpreis ist ohne Ausreißer näher an den Motordaten, d.h. der
Preis verhält sich ähnlich. Mit Ausreißer ist der Preis weit weg. Das
lässt sich so interpretieren, dass der Preis für sehr teure Autos nicht
mehr im Verhältnis zum Motor steht.
......
%% Cell type:markdown id:0001-9c88d904212173177e3cd805c405ca6bffb6c39ce47a88ff66351aa9536 tags: %% Cell type:markdown id:0001-d947a237f8749d5a07e6b16afc9277567861c9725260e81c2bffa0ec68d tags:
# MNIST visualisieren # MNIST visualisieren
In dieser Aufgabe wollen wir einen hochdimensionalen Datensatz in 2D In dieser Aufgabe wollen wir einen hochdimensionalen Datensatz in 2D
(oder 3D) plotten. Die Daten werden schon geladen. (oder 3D) plotten. Die Daten werden schon geladen und eine
Plotting-Funktion ist schon vorbereitet. *Hinweis: Der Code benötigt
einen Jupyter-Kontext, also Jupyter Lab oder VS Code mit interaktivem
Modus.*
%% Cell type:code id:0002-f9e5f87e267af56fbd5014863286132d368c2876d241287b849ceff60cc tags: %% Cell type:code id:0002-bbdfcc807a677cb51c1861eff7e69e8889bcc9c56d11ca63b972d0d11c7 tags:
``` ```
import io
import matplotlib.pyplot as plt
import numpy as np import numpy as np
import pandas as pd
import plotly.express as px import plotly.express as px
from plotly import graph_objects as go
from ipywidgets import VBox, Box, Image, Layout
from tensorflow.keras.datasets.mnist import load_data from tensorflow.keras.datasets.mnist import load_data
def interactive_scatter_plot(X_high, X_low, y):
"""
Make a scatter plot reacting on hover by showing the image
"""
assert X_high.shape[0] == X_low.shape[0] == y.shape[0], 'Arrays should have the same number of samples'
assert X_high.shape[1] > X_low.shape[1], 'First array should bei original images, second with reduced dimension'
x_name, y_name = 0, 1 if not isinstance(X_low, pd.DataFrame) else X_low.columns[:2]
scatter = px.scatter(X_low, x=x_name, y=y_name, color=y, hover_data={'idx': np.arange(len(X_low))})
scatter.update_xaxes(title_text=None)
scatter.update_yaxes(title_text=None)
# show image on hover
img = Image(format='png', width=56)
def update(trace, points, state):
# index relative to this trace (trace = color group)
trace_index = points.point_inds
if len(trace_index) == 0:
# this returns for traces not having the data point
return
# absolute indices of this trace
digit_indices = trace['customdata']
data_index = digit_indices[trace_index]
# convert image to PNG bytes and set image to it
rawBytes = io.BytesIO()
plt.imsave(rawBytes, X_high[data_index].reshape((28, 28)), format='png', cmap='gray')
rawBytes.seek(0)
img.value = rawBytes.read()
fig = go.FigureWidget(data=scatter.data, layout=scatter.layout)
# figure contains for each color a data trace and for each we have to define the on_hover function
for fig_data in fig.data:
fig_data.on_hover(update)
# layout of plot and centered image
return VBox([fig, Box([img], layout=Layout(display='flex', flex_flow='column', align_items='center'))])
# load data
(x_train, y_train), (x_test, y_test) = load_data() (x_train, y_train), (x_test, y_test) = load_data()
# reshape test set to 10 000 x 784 # reshape test set to 10 000 x 784
X = x_test.reshape(-1, 28 * 28) X = x_test.reshape(-1, 28 * 28)
``` ```
%% Cell type:markdown id:0003-fef1281e3edb72c906210479c5811c47fe2289914626b2c40534881280c tags: %% Cell type:markdown id:0003-8683c8202e9f2668b92e0aa78e49a38198e4d638b65ac30ec6020531315 tags:
Wenn Sie mögen ist hier ein Plot von verschiedenen Bildern der gleichen Wenn Sie mögen ist hier ein Plot von verschiedenen Bildern der gleichen
Klasse. So können Sie ein Blick reinwerfen. Klasse. So können Sie ein Blick in den Datensatz werfen.
%% Cell type:code id:0004-c879d58b500c83a0364d8680cc6b05c9cc97d36d3ea3743e112c56644db tags: %% Cell type:code id:0004-c879d58b500c83a0364d8680cc6b05c9cc97d36d3ea3743e112c56644db tags:
``` ```
# plot 50 examples for each digit # plot 50 examples for each digit
imgs = np.empty((50, 10, 28, 28)) imgs = np.empty((50, 10, 28, 28))
for j in range(10): for j in range(10):
imgs[:, j] = x_test[y_test == j][:50] imgs[:, j] = x_test[y_test == j][:50]
fig = px.imshow(imgs, animation_frame=0, facet_col=1, facet_col_wrap=5, binary_string=True) fig = px.imshow(imgs, animation_frame=0, facet_col=1, facet_col_wrap=5, binary_string=True)
fig.update_xaxes(showticklabels=False) fig.update_xaxes(showticklabels=False)
fig.update_yaxes(showticklabels=False) fig.update_yaxes(showticklabels=False)
fig.show() fig.show()
``` ```
%% Cell type:markdown id:0005-9f3a45468236a64a112ad49260df46a53eb308c1c3e503a34d2ae0c353f tags: %% Cell type:markdown id:0006-80f9722cacf3b6426928b4bbdb5fcb32d9d50cc0aaccb011c37c93b7f19 tags:
Transformieren Sie die Daten in 2D (ode 3D) und plotten die Transformieren Sie die Daten in 2D (ode 3D) und plotten die
Transformierten Daten als Scatter-Plot mit `y_test` als Transformierten Daten als Scatter-Plot mit `y_test` als
Farbunterscheidung. Farbunterscheidung. Für PCA ist es schon vorbereitet, aber probieren Sie
auch andere Techniken.
*Hinweis: Falls Sie UMAP verwenden wollen und es nicht installiert ist,
installieren Sie es mit `mamba install umap-learn`. Sie können es dann
mit `from umap import UMAP` importieren und wie jedes andere
Scikit-Learn-Modell verwenden.*
%% Cell type:code id:0007-ae5f11cf01a3212244c7bf86638455d0d6a145258c3112beb4c12633405 tags:
```
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
plot = interactive_scatter_plot(X, X_pca, y_test)
display(plot) # display from IPython.display implicitly in Jupyter imported, which is required anyway
```
......
%% Cell type:markdown id:0014-5250011056ff5724f9be1f73922489ac25747bd60219961556539182e36 tags:
# Book-Crossing
In dieser Aufgabe ist ein echter Datensatz aus dem Jahr 2004 gegeben,
bestehend aus:
- `books.csv.zst`
- `ratings.csv.zst`
- `users.csv.zst`
Er stammt von – einer Community um Bücher weiterzugeben und zu tracken.
Dabei können Bücher auch bewertet werden.
*Hinweis: Die Bewertungen haben eine skala von 1 – 10. Eine 0 meint
*implizite Bewertung*, also es wurde keine Bewertung abgegeben. Der
Begriff *implizite Bewertung\* steht dafür, dass man aus anderen Daten
eine Bewertung erahnen kann – hier z. B., dass es überhaupt gelesen
wurde.\*
Laden Sie die Daten, säubern sie ein bisschen und versuchen Sie zwei
Fragen zu beantworten:
1. Welches ist das meistbewertetste Buch (implizit und explizit) von
deutschen Nutzern und welche Durchschnittsbewertung (explizit) hat
es von deutschen Nutzern?
2. Ermitteln Sie die 20 populärsten Bücher von deutschen Nutzern.
Popularität definieren wir einfach als Summe von Bewertung eines
Buches (ohne, wie beim Mittelwert, durch die Anzahl zu teilen).
Plotten Sie Popularität gegen mittlere Bewertung (von deutschen
Nutzern) als Scatter-Plot und überlegen, was es bedeutet, wenn
Bücher eine große Popularität, aber eine relativ geringe mittlere
Bewertung haben. Welches ist das bestbewertetste Buch und welches
das schlechtbewertetste Buch der 20 populärsten Bücher (von
deutschen Nutzern)?
## Lösung
Die CSV-Dateien sind mit
[ZStandard](https://de.wikipedia.org/wiki/Zstandard) komprimiert. Die
Dateigrößen betragen
- `books.csv.zst`: 6.3 MiB (unkomprimiert: 22.5 MiB)
- `ratings.csv.zst`: 4.5 MiB (unkomprimiert: 21.6 MiB)
- `users.csv.zst`: 1.8 MiB (unkomprimiert: 10.5 MiB)
Komprimieren lohnt sich also und kann, falls das conda-forge `zstd`
installiert ist, einfach über die Kommandozeile erfolgen:
``` bash
zstd -19 -T8 DATEI
```
wobei `-19` für den höchsten Kompressionsgrad steht und `-T8` für acht
Threads. Aus Python heraus, kann man einen DataFrame beim Schreiben
einfach komprimieren:
``` bash
df.to_csv('dateiname.csv.zst', compression='zstd')
```
Aber nun zur eigentlichen Aufgabe. Wir laden zunächst die Bücherdaten
und weil wir das vorher schon mal ausprobiert haben, wissen wir aus
`books.Year.value_counts().sort_index()`, dass viele 0en vorkommen und
einige Werte nach 2004, obwohl der Datensatz 2004 heraus kam. Diese
setzen wir auf NaN.
%% Cell type:code id:0015-bb9fc0c5122136aaf4c40cf8da1b7b7b7d57f276031fcfa306591d1b6f4 tags:
```
import numpy as np
import pandas as pd
books = pd.read_csv('books.csv.zst', na_values={'Year': 0}, index_col='ISBN')
books.loc[books.Year > 2004, 'Year'] = np.nan
```
%% Cell type:markdown id:0016-b5d50ad15c785ba6ec147e8b66e53bad3fb11b1ec557c188c12d75fc900 tags:
Leider scheint die Datei seltsam encodiert zu sein, was man z. B. an
folgendem Eintrag sehen kann:
%% Cell type:code id:0017-7f35cbf4ac608cf4068a67cc564d9d59f3dce233a983752cdf947a38399 tags:
```
books.loc['3404148665']
```
%% Output
Title Illuminati.
Author Dan Brown
Year 2003.0
Publisher L�¼bbe
Name: 3404148665, dtype: object
%% Cell type:markdown id:0019-e0511a78a997280f3a22641267ff7cbbd003003b3c0d98437eca200bf13 tags:
Es hat keine bekannte Kodierung funktioniert. Aber das ist auch nicht so
schlimm. Wir lassen es so.
Beim Laden der Bewertungen setzen wir den Wert für die implizite
Bewertung auf `np.nan`. Für das Alter löschen wir Werte für 0 – 12
Jahren und ab 100 Jahren. Dann fügen wir die drei DataFrames – genau wie
in den Folien – mit `pd.concat` zusammen.
%% Cell type:code id:0020-6275e339c7956156b66d6323bf00d5910e0b902ea22ec80ce5c396e6573 tags:
```
ratings = pd.read_csv('ratings.csv.zst', na_values={'Rating': 0}, index_col=['User-ID', 'ISBN'])
users = pd.read_csv('users.csv.zst', index_col='User-ID')
users.loc[(users.Age > 100) | (users.Age < 13), 'Age'] = np.nan
data = users.join(ratings).join(books)
```
%% Cell type:markdown id:0021-6ff1d925c5b700acad8db0743933296e31411e8c394b4144209423af064 tags:
Dann versuchen wir aus der Location das Land heraus zu suchen, aber wenn
man sich die Länderdaten dann mal mit `country.unique()` anschaut, sieht
man, dass viel Handarbeit für die Bereinigung notwendig ist:
%% Cell type:code id:0022-f7b3a4ca4a0003853f39293d35833e1bf166f7aae392bae05bf3575686b tags:
```
country = data.Location.str.rsplit(n=1, expand=True)[1]
country = country.str.replace('"', '').str.replace(',', '').str.replace('.', '').str.replace('>', '').str.replace('!', '')
country[(country == '\\n/a\\') | (country == 'n/a') | (country == 'na') | (country == 'away') | (country == 'tomorrow') | (country == 'space') | (country == 'universe') | (country == 'a') | (country == 'x') | (country == '')] = np.nan
country[(country == 'baden-württemberg') | (country == 'baden-wuerttemberg') | (country == 'nrw') | (country == 'deutschland') | (country == 'hamburg') | (country == 'hessen') | (country == 'sachsen') | (country == 'berlin') | (country == 'brandenburg') | (country == 'bremen') | (country == 'nordrhein-westfalen') | (country == 'niedersachsen')] = 'germany'
```
%% Cell type:markdown id:0023-0088f97deeddb19f8bc2cf72898870feab39ee266525f24e27c44cc4076 tags:
Damit können wir jetzt nach deutschen Nutzern filtern. Dann gruppieren
wir nach ISBN und ermitteln die Größen der Gruppen, die angeben, wie
häufig ein Buch bewertet wurde. Die sortieren wir und nehmen den ersten
Eintrag. Für die mittlere Bewertung des Buchs holen wir uns die Spalte
`Rating` von der Gruppe mit der ISBN-Nummer und mitteln sie.
%% Cell type:code id:0024-8bab088c1940b6a912779d502778c79f14d8902171357762f57ea7fd065 tags:
```
data_de = data[country == 'germany']
group_de = data_de.groupby('ISBN')
most_frequent = group_de.size().sort_values(ascending=False).iloc[[0]] # keep Series, we need index and count value
mean_rating = group_de.get_group(most_frequent.index[0])['Rating'].mean()
```
%% Cell type:code id:0025-1967d62696af602038f7ecd1265eccc02956bc05db5cc44e9786086b1fc tags:
```
print('Das meistbewertetste Buch unter deutschen Nutzern ist:'); \
print(books.loc[most_frequent.index[0]]); \
print(f'Es wurde {most_frequent.squeeze()}x bewertet und hat eine Durchschnittsbewertung von {mean_rating:.2f}.')
```
%% Output
Das meistbewertetste Buch unter deutschen Nutzern ist:
Title Wild Animus
Author Rich Shapero
Year 2004.0
Publisher Too Far
Name: 0971880107, dtype: object
Es wurde 141x bewertet und hat eine Durchschnittsbewertung von 4.43.
%% Cell type:markdown id:0026-0088f97deeddb19f8bc2cf72898870feab39ee266525f24e27c44cc4076 tags:
Damit können wir jetzt nach deutschen Nutzern filtern. Dann gruppieren
wir nach ISBN und ermitteln die Größen der Gruppen, die angeben, wie
häufig ein Buch bewertet wurde. Die sortieren wir und nehmen den ersten
Eintrag. Für die mittlere Bewertung des Buchs holen wir uns die Spalte
`Rating` von der Gruppe mit der ISBN-Nummer und mitteln sie.
%% Cell type:code id:0027-23a74603aa2626099b2936113ce6587a3a5a7168ff44a103851ccea35f3 tags:
```
popular_de = group_de['Rating'].sum().sort_values(ascending=False)
popular_de.name = 'Popularity'
rating_pop_de = data_de.groupby('ISBN')['Rating'].mean()
feat_de = pd.concat((rating_pop_de.loc[popular_de.index[:20]], popular_de.iloc[:20]), axis='columns')
# books.loc['3442541751']
```
%% Cell type:code id:0028-4a411135507534cc54b452dce68626a99de75677db3e96939e4faa1b4d2 tags:
```
print('Das Buch unter den 20 populärsten Bücher, das die schlechteste Bewertung ist:'); \
print(books.loc[feat_de.Rating.idxmin()])
```
%% Output
Das Buch unter den 20 populärsten Bücher, das die schlechteste Bewertung ist:
Title Wild Animus
Author Rich Shapero
Year 2004.0
Publisher Too Far
Name: 0971880107, dtype: object
%% Cell type:markdown id:0029-1178d06cf897baa5f235115d007e2639d4fb153fad1328d9c4b4864d05e tags:
Das ist dasselbe Buch wie vorhin!
%% Cell type:code id:0030-95bc5af9bae3ad8fa6b4a79f6e9eba8c9481ad7c454089221a212cdb18f tags:
```
print('Das am besten bewertete Buch ist leider nicht in den Daten enthalten:', feat_de.Rating.idxmax() in books.index)
```
%% Output
Das am besten bewertete Buch ist leider nicht in den Daten enthalten: False
%% Cell type:markdown id:0032-c19f1102d9cbccc06ab8668796de51df8be368acff958b01e0028cd267f tags:
Eine kurze Internetrecherche kommt zum Schluss, dass sich bei dem am
besten bewerteten Buch um Faust handelt.
Und hier der Plot:
%% Cell type:code id:0033-6dd9ba2730f89dd049b0c9f06e394371d71c60eb5987b4bec46c56867da tags:
```
feat_de.plot.scatter('Rating', 'Popularity')
```
%% Cell type:markdown id:0007-0eae7603b6d19844fc278f91526d3cdaf0b09213b80d7564d3b1c6d164d tags:
# Book-Crossing
In dieser Aufgabe ist ein echter Datensatz aus dem Jahr 2004 gegeben,
bestehend aus:
- `books.csv.zst`
- `ratings.csv.zst`
- `users.csv.zst`
Er stammt von – einer Community um Bücher weiterzugeben und zu tracken.
Dabei können Bücher auch bewertet werden.
*Hinweis: Die Bewertungen haben eine skala von 1 – 10. Eine 0 meint
*implizite Bewertung*, also es wurde keine Bewertung abgegeben. Der
Begriff *implizite Bewertung\* steht dafür, dass man aus anderen Daten
eine Bewertung erahnen kann – hier z. B., dass es überhaupt gelesen
wurde.\*
Laden Sie die Daten, säubern sie ein bisschen und versuchen Sie zwei
Fragen zu beantworten:
1. Welches ist das meistbewertetste Buch (implizit und explizit) von
deutschen Nutzern und welche Durchschnittsbewertung (explizit) hat
es von deutschen Nutzern?
2. Ermitteln Sie die 20 populärsten Bücher von deutschen Nutzern.
Popularität definieren wir einfach als Summe von Bewertung eines
Buches (ohne, wie beim Mittelwert, durch die Anzahl zu teilen).
Plotten Sie Popularität gegen mittlere Bewertung (von deutschen
Nutzern) als Scatter-Plot und überlegen, was es bedeutet, wenn
Bücher eine große Popularität, aber eine relativ geringe mittlere
Bewertung haben. Welches ist das bestbewertetste Buch und welches
das schlechtbewertetste Buch der 20 populärsten Bücher (von
deutschen Nutzern)?
Hier Ihr Code:
%% Cell type:code id:0008-44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 tags:
```
```
File added
File added
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment