J'utilise pySpark
et j'ai configuré mon dataframe avec deux colonnes représentant un prix d'actif quotidien comme suit:
ind = sc.parallelize(range(1,5))
prices = sc.parallelize([33.3,31.1,51.2,21.3])
data = ind.Zip(prices)
df = sqlCtx.createDataFrame(data,["day","price"])
J'obtiens en appliquant df.show()
:
+---+-----+
|day|price|
+---+-----+
| 1| 33.3|
| 2| 31.1|
| 3| 51.2|
| 4| 21.3|
+---+-----+
Ce qui est bien et tout. Je voudrais avoir une autre colonne qui contient les rendements quotidiens de la colonne des prix, c'est-à-dire quelque chose comme
(price(day2)-price(day1))/(price(day1))
Après de nombreuses recherches, on me dit que cela est plus efficacement accompli en appliquant les fonctions pyspark.sql.window
, Mais je ne peux pas voir comment.
Vous pouvez apporter la colonne du jour précédent en utilisant la fonction lag , et ajouter une colonne supplémentaire qui effectue le retour quotidien réel des deux colonnes, mais vous devrez peut-être indiquer spark comment partitionner vos données et/ou leur ordonner de faire du lag, quelque chose comme ceci:
from pyspark.sql.window import Window
import pyspark.sql.functions as func
from pyspark.sql.functions import lit
dfu = df.withColumn('user', lit('tmoore'))
df_lag = dfu.withColumn('prev_day_price',
func.lag(dfu['price'])
.over(Window.partitionBy("user")))
result = df_lag.withColumn('daily_return',
(df_lag['price'] - df_lag['prev_day_price']) / df_lag['price'] )
>>> result.show()
+---+-----+-------+--------------+--------------------+
|day|price| user|prev_day_price| daily_return|
+---+-----+-------+--------------+--------------------+
| 1| 33.3| tmoore| null| null|
| 2| 31.1| tmoore| 33.3|-0.07073954983922816|
| 3| 51.2| tmoore| 31.1| 0.392578125|
| 4| 21.3| tmoore| 51.2| -1.403755868544601|
+---+-----+-------+--------------+--------------------+
Voici une introduction plus longue à Fonctions de fenêtre dans Spark .
Lag La fonction peut vous aider à résoudre votre cas d'utilisation.
from pyspark.sql.window import Window
import pyspark.sql.functions as func
### Defining the window
Windowspec=Window.orderBy("day")
### Calculating lag of price at each day level
prev_day_price= df.withColumn('prev_day_price',
func.lag(dfu['price'])
.over(Windowspec))
### Calculating the average
result = prev_day_price.withColumn('daily_return',
(prev_day_price['price'] - prev_day_price['prev_day_price']) /
prev_day_price['price'] )