Eine Methode, Schleifen und begrenzte Rückblickzeiten zu vermeiden.
mit Ihrem Beispiel:
import pandas as pd
import numpy as np
>>>df = pd.DataFrame([['1/1/2000', 'Apple', 0.010, 0.75],
['1/1/2000', 'IBM', 0.011, 0.4],
['1/1/2000', 'Google', 0.012, 0.45],
['1/1/2000', 'Nokia', 0.022, 0.81],
['2/1/2000', 'Apple', 0.014, 0.56],
['2/1/2000', 'Google', 0.015, 0.45],
['2/1/2000', 'Nokia', 0.016, 0.55],
['3/1/2000', 'Apple', 0.020, 0.52],
['3/1/2000', 'Google', 0.030, 0.51],
['3/1/2000', 'Nokia', 0.040, 0.47]],
columns=['Date', 'Stock', 'Weight', 'Percentile'])
Zuerst identifizieren, wenn Bestände beginnen würde oder in Endgewicht verfolgt stoppen wird:
>>>df['bought'] = np.where(df['Percentile'] >= 0.7, 1, np.nan)
>>>df['bought or sold'] = np.where(df['Percentile'] < 0.5, 0, df['bought'])
Mit '1' eine Aktie angibt, zu kaufen, und ‚0 "Ein zu verkaufen, wenn es im Besitz ist.
Von diesem können Sie identifizieren, ob das Lager gehört. Beachten Sie, dass dies erfordert die Datenrahmen bereits chronologisch sortiert werden, wenn an irgendeiner Stelle Sie es auf einem Datenrahmen ohne Datum Index verwenden:
>>>df['own'] = df.groupby('Stock')['bought or sold'].fillna(method='ffill').fillna(0)
'ffill'
nach vorne füllen, Eigentumsverhältnisse ausbreitende uns darauf, von Kauf- und Verkaufsdaten. .fillna(0)
fängt alle Bestände ab, die für den gesamten Datenrahmen zwischen 0,5 und 0,7 verblieben sind. Dann Endgewicht
>>>df['Final Weight'] = df['own']*df['Weight']
Multiplikation berechnen, mit df['own']
die Identität oder gleich Null ist, ist ein wenig schneller als ein anderer np.where und gibt das gleiche Ergebnis.
Edit:
Da Geschwindigkeit ein Anliegen ist, alles in einer Spalte zu tun, wie @cronos vorgeschlagen, einen Geschwindigkeitsschub liefert, kommt in um eine 37% ige Verbesserung bei 20 Zeilen in meinen Tests, oder 18% bei 2.000.000. Ich könnte mir vorstellen, dass Letzteres größer wäre, wenn das Speichern der Zwischenspalten eine Art Speicherverbrauchsschwelle überschreiten würde oder es etwas anderes mit Systemspezifikationen gäbe, die ich nicht erfahren hätte.
Dies würde wie folgt aussehen:
>>>df['Final Weight'] = np.where(df['Percentile'] >= 0.7, 1, np.nan)
>>>df['Final Weight'] = np.where(df['Percentile'] < 0.5, 0, df['Final Weight'])
>>>df['Final Weight'] = df.groupby('Stock')['Final Weight'].fillna(method='ffill').fillna(0)
>>>df['Final Weight'] = df['Final Weight']*df['Weight']
Entweder diese Methode oder das Löschen der Zwischen Feldern Ergebnis geben würde:
>>>df
Date Stock Weight Percentile Final Weight
0 1/1/2000 Apple 0.010 0.75 0.010
1 1/1/2000 IBM 0.011 0.40 0.000
2 1/1/2000 Google 0.012 0.45 0.000
3 1/1/2000 Nokia 0.022 0.81 0.022
4 2/1/2000 Apple 0.014 0.56 0.014
5 2/1/2000 Google 0.015 0.45 0.000
6 2/1/2000 Nokia 0.016 0.55 0.016
7 3/1/2000 Apple 0.020 0.52 0.020
8 3/1/2000 Google 0.030 0.51 0.000
9 3/1/2000 Nokia 0.040 0.47 0.000
Zur weiteren Verbesserung, ich das Hinzufügen einer Art und Weise aussehen würde zu setzen eine anfängliche Bedingung, bei der sich Aktien im Besitz befinden, gefolgt von einer Zerlegung des Datenrahmens in kleinere Zeitrahmen. Dies könnte durch das Hinzufügen einer Anfangsbedingung für den Zeitraum von einem dieses kleineren Datenrahmen bedeckt getan wird, dann
Wechsel
>>>df['Final Weight'] = np.where(df['Percentile'] >= 0.7, 1, np.nan)
um so etwas wie
>>>df['Final Weight'] = np.where((df['Percentile'] >= 0.7) | (df['Final Weight'] != 0), 1, np.nan)
zu, dass erkannt werden zu lassen und verbreiten.
Haben Sie einen versuchten Code, um uns zu zeigen? –
Der Code, den ich schrieb, wenn ich sehr ähnlich zu PiRSquaredes unten antworte, aber das sieht nur vor einem Tag, ich wollte eine nette Pandas Weg, es vorzugsweise ohne Schleifen zu tun, weil der Datensatz riesig ist – MysterioProgrammer91