Hallo Zusammen,
Ursprünglich komme ich aus der Statistik & Datenbank - Ecke und bin in Python ziemlicher Anfänger. Entsprechend habe bei meinem Problem auch schon ein paar Ideen durchprobiert, komme aber auf keinen grünen Zweig.
Vielleicht könnt Ihr mir ein paar Tips geben zur Lösung meines Problems. Skriptschnipsel lehne ich natürlich auch nicht ab
Im Prinzip geht es um eine Art Abschreibungsberechnung. Ich habe einen Anfangsbestand, eine Zeitachse (Periode) und für jede Periode eine spezifische Abschreibungsrate (bzw. hier Survival Rate = 1-Abschreibungsrate)
Mein Ausgangspunkt:
1) Ein Dataframe mit einer ID (z.B. für jedes Abschreibungsobjekt), einer Zeiteinheit und einem Faktor im Sinne einer Survival Rate.
Lesebeispiel: In Periode 4 ist Objekt mit ID1 nur noch 0,99 vom Wert der Vorperiode 3.
df_start = pd.DataFrame({
'id' : [1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3],
'zeit' : [1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,11,12,13,1,2,3,4,5,6,7,8,9,10,11],
'faktor' : [1,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,1,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,1,0.9,0.9,0.9,0.9,0.7,0.7,0.7,0.7,0.7,0.7],
})
2) die Ausgangswerte - Der Wert jeder ID-Nummer zum Zeitpunkt 1:
df_basis = pd.DataFrame ({"id": [1,2,3],
"wert": [100, 200, 300]})
Mein Ziel:
df_ziel = pd.DataFrame({
'id' : [1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3],
'zeit' : [1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,11,12,13,1,2,3,4,5,6,7,8,9,10,11],
'faktor' : [1,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,1,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,1,0.9,0.9,0.9,0.9,0.7,0.7,0.7,0.7,0.7,0.7],
'ergebnis' : [100,99,98.01,97.0299,96.059601,95.09900499,94.1480149401,93.206534790699,92.274469442792,91.3517247483641,200,190,180.5,171.475,162.90125,154.7561875,147.018378125,139.66745921875,132.684086257812,126.049881944922,119.747387847676,113.760018455292,108.072017532527,300,270,243,218.7,196.83,137.781,96.4467,67.51269,47.258883,33.0812181,23.15685267]
})
Das Ergebnis berechnet sich dabei jeweils aus dem Wert der Vorperiode * Faktor der Periode.
Also z.B. Startwert 100 in Periode 1 reduziert sich zu 100*0,99 in Periode 2 zu 100*0,99*0,99 in Periode 3, usw.
Da sich die Faktoren im Zeitverlauf ändern können, ist eine einfaches "100*faktor**zeit" leider keine Option.
Meine Herausforderung:
Wie schaffe ich es, zeilenübergreifend zu arbeiten und den Wert einer Periode aus dem Wert der Vorperiode zu berechnen?
Wäre toll, wenn Ihr ein paar Ideen und Tips für mich hättet.
Beste Grüße
Peter
Abschreibung / Berechnung auf Basis vorhergehender Zeilen
- __blackjack__
- User
- Beiträge: 13163
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Schau Dir mal die `shift()`-Methode an, ob Dir die eventuell weiterhilft.
“There will always be things we wish to say in our programs that in all known languages can only be said poorly.” — Alan J. Perlis
Die Datenstruktur ist für solche Daten vielleicht nicht die beste. Die mathematische Operation, die du brauchst, ist cumprod. Da du für jedes Objekt eine unterschiedliche Anzahl an Zeitschritten hast, macht die Sache schwierig
Vielen Dank für den Tip! Für die erste ID passiert genau das, was ich am Ende haben will. Aber wie bringe ich Python dazu, bei der zweiten ID wieder von vorne anzufangen?
Mein Versuch mit
for i in df['id']:
df['test'] = df['faktor'].cumprod(axis=0)
führte jedenfalls nicht zum gewünschten Resultat
- __blackjack__
- User
- Beiträge: 13163
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Peter1974: Da wird man nach ID gruppieren müssen → `groupby()`.
“There will always be things we wish to say in our programs that in all known languages can only be said poorly.” — Alan J. Perlis
Sehr cool__blackjack__ hat geschrieben: ↑Freitag 25. September 2020, 17:10 @Peter1974: Da wird man nach ID gruppieren müssen → `groupby()`.
Am Ende wird aus dem ganzen Problem ein sehr überschaubarer Zweizeiler:
gdf = df.groupby('id', group_keys = True)
df['test'] = gdf['faktor'].cumprod(axis=0)
Bin begeistert!
Vielen Dank Euch beiden für die guten Tips!