Fehlermeldung bei Verwenden von widgets.IntSlider

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
derCode-Neuling
User
Beiträge: 2
Registriert: Montag 23. Mai 2022, 11:11

Hallo Zusammen, ich lerne seit kurzer Zeit Programmieren und komme an einem Punkt nicht weiter. Mein Ziel ist es, ein Dataframe auszugeben was die meist bewerteten Filme anzeigt. Die Columns des DF sind: movieID, Titel des Films, und Anzahl der erhaltenen Bewertungen. Die Ausgabe des Dataframes wie ich es haben will klappt alles, jetzt würde ich gern ein Slider einfügen, bei dem der Nutzer durch verschieben des Reglers (z.B. von 3 auf 5), sich die Menge der ausgegebenen (meist bewerteten) Filme ändert (sprich: nicht mehr die top 3 Filme sondern jetzt top 5 Filme).

Code: Alles auswählen

def most_rated_film(df1,df2,anzahl):
    dfmovies = df1
    dfratings = df2
    dfmerge = pd.merge(dfmovies,dfratings,on = "movieId") 
    
    dfmerge["Menge der Bewertungen"] = 1
    dfmenge = dfmerge.groupby("movieId")["Menge der Bewertungen"].sum()
    dfmenge = dfmenge.to_frame()
    dfmenge = dfmenge.reset_index()
    dfzusammen = pd.merge(movies,dfmenge,on = "movieId")
    countpermovie = dfzusammen.sort_values("Menge der Bewertungen", axis = 0,ascending = False)
    countpermovie = countpermovie.reset_index()
    countpermovie = countpermovie[["movieId","title","Menge der Bewertungen"]]
    countpermovie.rename(columns={'title':'Titel des Films',
                                 'Menge der Bewertungen':'Anzahl der erhaltenen Bewertungen'},inplace=True)
    return countpermovie.head(anzahl)
Wenn ich hierbei die Funktion wie folgt aufrufe:

Code: Alles auswählen

most_rated_film(movies,ratings,10)
-> funktioniert alles und mir werden die 10 Filme mit den meisten Bewertungen angezeigt.

Jetzt mit dem Slider Funktioniert das leider nicht:

Code: Alles auswählen

set_anzahl = widgets.IntSlider(min=1, max=20, step=1, value=1, description="Anzahl:")
most_rated_film(movies, ratings, set_anzahl)
Dann erhalte ich diese Fehlermeldung, wäre sehr korrekt wenn mir jemand helfen kann ?
ps. dass der Code nicht sehr anschaulich ist, ist mir bewusst :D

---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/var/folders/r1/txm07tps00s295995cqyrs2w0000gn/T/ipykernel_8101/1253293865.py in <module>
2
3 set_anzahl = widgets.IntSlider(min=1, max=20, step=1, value=1, description="Anzahl:")
----> 4 most_rated_film(movies, ratings, set_anzahl)

/var/folders/r1/txm07tps00s295995cqyrs2w0000gn/T/ipykernel_8101/3440946735.py in most_rated_film(df1, df2, anzahl)
15 countpermovie.rename(columns={'title':'Titel des Films',
16 'Menge der Bewertungen':'Anzahl der erhaltenen Bewertungen'},inplace=True)
---> 17 return countpermovie.head(anzahl)

~/opt/anaconda3/lib/python3.9/site-packages/pandas/core/generic.py in head(self, n)
5071 5 parrot
5072 """
-> 5073 return self.iloc[:n]
5074
5075 @final

~/opt/anaconda3/lib/python3.9/site-packages/pandas/core/indexing.py in __getitem__(self, key)
929
930 maybe_callable = com.apply_if_callable(key, self.obj)
--> 931 return self._getitem_axis(maybe_callable, axis=axis)
932
933 def _is_scalar_access(self, key: tuple):

~/opt/anaconda3/lib/python3.9/site-packages/pandas/core/indexing.py in _getitem_axis(self, key, axis)
1541
1542 if isinstance(key, slice):
-> 1543 return self._get_slice_axis(key, axis=axis)
1544
1545 if is_iterator(key):

~/opt/anaconda3/lib/python3.9/site-packages/pandas/core/indexing.py in _get_slice_axis(self, slice_obj, axis)
1576
1577 labels = obj._get_axis(axis)
-> 1578 labels._validate_positional_slice(slice_obj)
1579 return self.obj._slice(slice_obj, axis=axis)
1580

~/opt/anaconda3/lib/python3.9/site-packages/pandas/core/indexes/base.py in _validate_positional_slice(self, key)
3682 """
3683 self._validate_indexer("positional", key.start, "iloc")
-> 3684 self._validate_indexer("positional", key.stop, "iloc")
3685 self._validate_indexer("positional", key.step, "iloc")
3686

~/opt/anaconda3/lib/python3.9/site-packages/pandas/core/indexes/base.py in _validate_indexer(self, form, key, kind)
5717
5718 if key is not None and not is_integer(key):
-> 5719 raise self._invalid_indexer(form, key)
5720
5721 def _maybe_cast_slice_bound(self, label, side: str_t, kind=no_default):

TypeError: cannot do positional indexing on RangeIndex with these indexers [IntSlider(value=1, description='Anzahl:', max=20, min=1)] of type IntSlider
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Ein IntSlider-Objekt ist keine ganze Zahl, also kannst Du auch nicht so tun, als ob es eine wäre. IntSlider-Objekte haben ein `value`-Attribut, das den aktuellen Wert enthält.

Warum nennst du die Parameter df1 und df2 erst in der Funktion in sinnvolle Namen um, und nimmst diese Namen nicht schon von vornherein als Argumente?
`dfmerge` ist an drei verschiedene Dataframes gebunden. Und dann gibt es diesen Namen auch noch in "deutscher" Übersetzung, wie soll man da die Bedeutung der einzelnen Objekte auseinanderhalten können?

`movies` kommt aus dem Nichts. Aber alles was eine Funktion an Daten braucht, muß sie über ihre Argumente bekommen. Was ist der Unterschied zwischen dfmovies und movies? Das nichts-sagende df-Präfix macht den Unterschied nicht deutlich. Es ist wichtig, gute Variablennamen zu verwenden, damit man den Code auch verstehen kann, und verstehen muß man ihn, um Fehler zu finden und gleich zu vermeiden.
Benutzeravatar
__blackjack__
User
Beiträge: 14078
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@derCode-Neuling: Ist `dfmerge` überhaupt notwendig? Statt eine Spalte mit 1en zu erstellen und die beim Gruppieren zu addieren, könnte man einfach `count()` verwenden.

Wobei ich mich gerade Frage ob das Verschmelzen von den Filmen und den Bewertungen *vor* dem Zählen überhaupt sinnvoll ist. Wäre es nicht viel sinnvoller die Bewertungen nach "movieId" zu gruppieren und zu zählen und dann erst das ganze mit den Filmen zu verschmelzen um an die Titel zu kommen.

Warum wird eine Spalte "Menge der Bewertungen" eingeführt, die am Ende in "Anzahl der erhaltenen Bewertungen" umbenannt wird? Der Spalte hätte man gleich den endgültigen Namen geben können.

`axis=0` ist bei `DataFrame.sort_values()` der Defaultwert.

Da käme dann etwa so etwas bei heraus:

Code: Alles auswählen

def most_rated_film(movies, ratings, anzahl):
    count_column_name = "Anzahl der erhaltenen Bewertungen"
    return (
        movies.merge(
            ratings.groupby("movieId")
            .count()
            .rename(columns={"rating": count_column_name}),
            on="movieId",
        )
        .sort_values(count_column_name, ascending=False)
        .rename(columns={"title": "Titel des Films"})
        .head(anzahl)
    )
Sollte `movies` mehr Spalten als die ID und den Filmtitel enthalten, sollte man diese beiden als ersten Schritt selektieren, um nicht unnötige Daten durch den ganzen Ausdruck mit zu schleppen:

Code: Alles auswählen

def most_rated_film(movies, ratings, anzahl):
    count_column_name = "Anzahl der erhaltenen Bewertungen"
    return (
        movies[["movieId", "title"]]
        .merge(
            ratings.groupby("movieId")
            .count()
            .rename(columns={"rating": count_column_name}),
            on="movieId",
        )
        .sort_values(count_column_name, ascending=False)
        .rename(columns={"title": "Titel des Films"})
        .head(anzahl)
    )
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten