Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Python-de] Verstaendnisproblem

11 views
Skip to first unread message

eilfh

unread,
Feb 11, 2021, 6:35:37 AM2/11/21
to
Hallo,

bin noch Anfänger in python,
vielleicht sieht ein Profi mit einem Blick, wo mein Fehler liegt


Bsp.

x1 = df.loc[df.A == '7', 'Z1']
#print(x1) # okay, z.Bsp. 99
x2 = 120
x3 = 3
x4 = df.loc[df.A == '8', 'Z1']
#print(x4) # okay, z.Bsp. 77


d1 = x2 - x1 # okay 21
d2 = x4 - x3 # okay 74

aber:
d3 = d2 - d1 # ---> NaN
oder
d4 = (x2 - x1 + x4 - x3) # ---> NaN


ich hab schon einige "Klimmzüge" gemacht,
bin aber bisher an dieser vermeintlichen Banalität gescheitert



Vielen Dank im Voraus

Frank




Stefan Schwarzer

unread,
Feb 11, 2021, 7:20:01 AM2/11/21
to
On 2021-02-11 12:35, eilfh wrote:
> bin noch Anfänger in python,
> vielleicht sieht ein Profi mit einem Blick, wo mein Fehler liegt
>
> Bsp.
>
> x1 = df.loc[df.A == '7', 'Z1']
> #print(x1) # okay, z.Bsp. 99
> x2 = 120
> x3 = 3
> x4 = df.loc[df.A == '8', 'Z1']
> #print(x4) # okay, z.Bsp. 77
>
>
> d1 = x2 - x1 # okay 21
> d2 = x4 - x3 # okay 74
>
> aber:
> d3 = d2 - d1 # ---> NaN
> oder
> d4 = (x2 - x1 + x4 - x3) # ---> NaN

Aus der Verwendung von `df.loc` schließe ich, dass es um
ein pandas DataFrame geht.

Wenn ich mit

In [28]: df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})

In [29]: df
Out[29]:
A B
0 1 4
1 2 5
2 3 6

In [30]: df.loc[df.A == 1, 'B']
Out[30]:
0 4
Name: B, dtype: int64

einen Zugriff ähnlich wie in deinem Beispiel eingebe,
bekomme ich keinen Skalar, sondern ein `pandas.Series`-
Objekt. Ich _vermute_ daher, dass du das Beispiel zu
sehr vereinfacht hast bzw. in deiner Mail etwas steht,
was sich nicht mit der tatsächlichen Abfolge der Befehle
deckt.

Dass du NaNs bekommst, obwohl an derselben Stelle
mutmaßlich andere Werte stehen sollten, weckt bei mir
den Eindruck, dass du Slices hast, die dieselben
Speicherstellen referenzieren, wie sie im ursprünglichen
DataFrame stehen und dass du das DataFrame verändert
hast und danach wieder auf deine Slices guckst, die auf
die neuen Werte im DataFrame verweisen. Diese
Assoziation deckt sich aber nicht mit deinem Beispiel.

Ich glaube, das beste ist, wenn du eine Python-Datei
mit einem minimalen Beispiel erzeugst, das bei
Ausführung der Datei die mutmaßlich falsche Ausgabe
zeigt. Wenn du die Befehle dagegen in einem Jupyter
Notebook ausführst, musst du sehr aufpassen, weil der
Zustand des Notebooks von der Folge deiner ausgeführten
Befehle abhängt, nicht von der Reihenfolge der Zellen
im Notebook.

So gesehen, also keine Lösung deines Problems, aber
vielleicht ein paar nützliche Hinweise zu dessen
Ergründung. :-) Es würde mich interessieren, ob es
weiterhilft.

Viele Grüße
Stefan

eilfh

unread,
Feb 11, 2021, 12:29:49 PM2/11/21
to
Am Donnerstag, 11. Februar 2021, 13:19:56 CET schrieb Stefan Schwarzer:
Hallo, Stefan

vielen Dank für Deine schnelle Antwort



Vorhanden sind (neben Anfängerwissen über python, pandas & co.)

eine (Excel-)Tabelle mit Zählerständen zu konkreten Terminen,
die ich in ein pandas-Dataframe eingelesen habe.

Mit df...shift(1) kann ich die Differenzen zwischen Zählerablesungen bestimmen.



Gelegentlich wird auch ein Zähler ausgetauscht.

x1 sei die letzte Ablesung vor dem Tausch
x2, x3 seien Ausbau- bzw. Einbauzählerstand
x4 erste Ablesung nach dem Tausch
(x5 sei die (Zeit-)Differenz zischen den beiden routinemäßigen Ablesungen.)


Der neu zu berechnende Verbrauch wäre dann

v = (x2 - x1 + x4 - x3) / x5



> bekomme ich keinen Skalar, sondern ein `pandas.Series`- Objekt.

Du hast recht, das war ein entscheidender Hinweis!

statt:
x1 = df.loc[df.Datum == '1993-09-09', 'Spalte_7']
---> 55 490

besser:
x1 = df.at[55, 'Spalte_7']
---> 490 (der gesuchte Skalar)


aber woher/womit erfahre ich die "rowid" 55 ?
(... .ix is deprecated. ....)
D.h. die "Zeile" mit dem Datum == '1993-09-09'


aa = df.iloc["1993-09-09"]
TypeError: cannot do positional indexing on <class
'pandas.core.indexes.range.RangeIndex'> with these indexers
[1993-09-09] of <class 'str'>

Datum datetime64[ns], aber nicht als Index

df.set_index('Datum')
# nach dem Einlesen, bringt nicht den erwarteten/erhofften Effekt


Vielen Dank

Frank


Peter Otten

unread,
Feb 11, 2021, 1:00:32 PM2/11/21
to
On 11/02/2021 18:29, eilfh wrote:
> Am Donnerstag, 11. Februar 2021, 13:19:56 CET schrieb Stefan Schwarzer:
> Hallo, Stefan
>
> vielen Dank für Deine schnelle Antwort
>
>
>
> Vorhanden sind (neben Anfängerwissen über python, pandas & co.)
>
> eine (Excel-)Tabelle mit Zählerständen zu konkreten Terminen,
> die ich in ein pandas-Dataframe eingelesen habe.
>
> Mit df...shift(1) kann ich die Differenzen zwischen Zählerablesungen bestimmen.
>
>
>
> Gelegentlich wird auch ein Zähler ausgetauscht.
>
> x1 sei die letzte Ablesung vor dem Tausch
> x2, x3 seien Ausbau- bzw. Einbauzählerstand
> x4 erste Ablesung nach dem Tausch
> (x5 sei die (Zeit-)Differenz zischen den beiden routinemäßigen Ablesungen.)
>
>
> Der neu zu berechnende Verbrauch wäre dann
>
> v = (x2 - x1 + x4 - x3) / x5
>
>
>
>> bekomme ich keinen Skalar, sondern ein `pandas.Series`- Objekt.
>
> Du hast recht, das war ein entscheidender Hinweis!
>
> statt:
> x1 = df.loc[df.Datum == '1993-09-09', 'Spalte_7']
> ---> 55 490
>
> besser:
> x1 = df.at[55, 'Spalte_7']
> ---> 490 (der gesuchte Skalar)
>
>
> aber woher/womit erfahre ich die "rowid" 55 ?

Brauchst Du denn die Zeile? Eine Series mit genau einem Wert

>>> x
0 4
Name: B, dtype: int64
>>> type(x)
<class 'pandas.core.series.Series'>


kannst Du einfach entpacken

>>> [y] = x
>>> y
4
>>> type(y)
<class 'int'>

oder wenn du weißt, dass Du z. B. eine Fließkommazahl erwartest, direkt
konvertieren:

>>> float(x)
4.0

eilfh

unread,
Feb 12, 2021, 9:29:23 AM2/12/21
to
Am Donnerstag, 11. Februar 2021, 18:48:23 CET schrieb Peter Otten:
Hallo, Peter

danke für Deine Antwort.

Das war das fehlende Puzzle in meinem Programm

> >>> x
>
> 0 4
> Name: B, dtype: int64
>
> >>> type(x)
>
> <class 'pandas.core.series.Series'>
>
>
> kannst Du einfach entpacken
>
> >>> [y] = x
> >>> y
>
> 4


um ehrlich zu sein, ich versteh's zwar nicht,
aber es läuft und erfüllte genau den Zweck


Danke

Frank


Stefan Schwarzer

unread,
Feb 12, 2021, 10:07:52 AM2/12/21
to
Falls du `[y] = x` meinst, kann ich mir vorstellen, dass das
komisch aussieht. Das ist sogenanntes implizites "Tuple
unpacking", hier vielleicht eher "List unpacking". Du kannst
das auch als `y = x[0]` schreiben; ich denke, das ist klarer.

Die Schreibweise `[y] = x` hat allerdings wiederum den Vorteil,
dass du eine Exception bekommst, wenn `x` mehr als ein zu
"entpackendes" Element enthält, obwohl du das in deinem Code
nicht erwartest.

Viele Grüße
Stefan

eilfh

unread,
Feb 12, 2021, 10:10:18 AM2/12/21
to
Am Freitag, 12. Februar 2021, 16:07:48 CET schrieb Stefan Schwarzer:

vielen Dank für Deine Erklärung


MfG

Frank




Peter Otten

unread,
Feb 12, 2021, 11:30:16 AM2/12/21
to
On 12/02/2021 16:07, Stefan Schwarzer wrote:
> On 2021-02-12 15:29, eilfh wrote:
>> Am Donnerstag, 11. Februar 2021, 18:48:23 CET schrieb Peter Otten:
>> Hallo, Peter
>>
>> danke für Deine Antwort.
>>
>> Das war das fehlende Puzzle in meinem Programm
>>
>>> >>> x
>>>
>>> 0 4
>>> Name: B, dtype: int64
>>>
>>> >>> type(x)
>>>
>>> <class 'pandas.core.series.Series'>
>>>
>>>
>>> kannst Du einfach entpacken
>>>
>>> >>> [y] = x
>>> >>> y
>>>
>>> 4
>>
>>
>> um ehrlich zu sein, ich versteh's zwar nicht,
>> aber es läuft und erfüllte genau den Zweck
>
> Falls du `[y] = x` meinst, kann ich mir vorstellen, dass das
> komisch aussieht. Das ist sogenanntes implizites "Tuple
> unpacking", hier vielleicht eher "List unpacking". Du kannst
> das auch als `y = x[0]` schreiben; ich denke, das ist klarer.

Wenn x vom Typ tuple oder list ist, gerne; aber pandas ist ziemlich
komplex und hält immer eine Überraschung bereit:

>>> df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
>>> ser = df.loc[df.A == 1, "B"]
>>> ser[0]
4

Scheint zu funktionieren, ist aber Zufall:

>>> ser = df.loc[df.A == 2, "B"]
>>> ser[0]
Traceback (most recent call last):
[...]
KeyError: 0

Mit Unpacking:

>>> [y] = ser
>>> y
5

D. h. eine Series verhält sich beim Iterieren wie eine Liste, beim
Lookup wie ein dict.

eilfh

unread,
Feb 12, 2021, 11:42:08 AM2/12/21
to
Am Freitag, 12. Februar 2021, 17:30:04 CET schrieb Peter Otten:
Hallo, Peter

hm,

ich stau'n nur bauklötzer

da muss ich noch einiges dazu lernen und
damit experimentieren



Danke


Frank






> _______________________________________________
> python-de maillist - pyth...@python.org
> https://mail.python.org/mailman/listinfo/python-de




Mike Müller

unread,
Feb 12, 2021, 3:48:04 PM2/12/21
to
Am 12.02.21 um 17:30 schrieb Peter Otten:
> On 12/02/2021 16:07, Stefan Schwarzer wrote:
>> On 2021-02-12 15:29, eilfh wrote:
>>> Am Donnerstag, 11. Februar 2021, 18:48:23 CET schrieb Peter Otten:
>>> Hallo, Peter
>>>
Wenn du das erste Element möchtest solltest du den Zugriff "position based" [1]
machen:

>>> ser.iloc[0]
5

Dagegen ist:

>>> ser[0]

"label based"

und entspricht:

>>> ser.loc[0]

Außerdem kann man nach `loc` und `iloc` besser googeln als nach `[y] = ser`. ;)

[1]
https://pandas.pydata.org/docs/user_guide/indexing.html#different-choices-for-indexing

>
> Mit Unpacking:
>
> >>> [y] = ser
> >>> y
> 5
>
> D. h. eine Series verhält sich beim Iterieren wie eine Liste, beim Lookup wie
> ein dict.
>

eilfh

unread,
Feb 14, 2021, 9:04:29 AM2/14/21
to
Am Freitag, 12. Februar 2021, 21:32:46 CET schrieb Mike Müller:

Hallo, Maik,


> Wenn du das erste Element möchtest solltest du den Zugriff "position based"
> [1]
> machen:
> >>> ser.iloc[0]
>
> 5

Gut zu wissen


das erste Element ist in dem Fall die Rowid,
das zweite Element der Zählerstand

Geniest das schöne Wetter zum Restsonntag und
danke für die Info


Frank


0 new messages