Pyspark列转换:计算列中每个组的百分比变化

时间:2019-08-13 02:15:40

标签: pyspark

我在本地计算机上使用Pyspark。我有一个火花数据框架,其中包含450万行和大约30,000种不同的股票。我需要计算每只股票随时间变化的百分比。我已经运行了orderBy,以便将所有股票归为一组(如下例所示)。

下面是一个简化的示例数据框。

df = spark.read.csv("stock_price.txt", header=True, inferSchema=True)
df.show()

**Company**     **Price**
Company_A         100
Company_A         103
Company_A         105
Company_A         107
Company_B          23
Company_B          25
Company_B          28
Company_B          30

我想要的输出将是这样

**Company**     **Price**     **%_Change**
Company_A         100              0
Company_A         103              3%
Company_A         105              2%
Company_A         107              2%
Company_B          23              0
Company_B          25              9%
Company_B          28              12%
Company_B          30              7%

技巧(以我的观点)是建立一个可以完成两件事的代码: 1)确定每次列出新库存 2)开始计算该股票第二次观察的百分比变化,并继续计算百分比变化,直到最后一次观察。它需要从第二次观察开始,因为在第二次观察发生之前不会有百分比变化。

2 个答案:

答案 0 :(得分:1)

我相信Windows是前往这里的方式

一些进口

from pyspark.sql.window import Window
from pyspark.sql.functions import lag

partitionBy('Company')将我们的库存保持在一起。我在这里按价格订购,但是可能要等到您的日期时间

win = Window.partitionBy('Company').orderBy('Price')

借助lag更改了计算百分比,该百分比在窗口中获取了先前的值

df.withColumn('perc_change', (df.Price - lag(df['Price']).over(win))/100).show()

+---------+-----+-----------+
|  Company|Price|perc_change|
+---------+-----+-----------+
|Company_B|   23|       null|
|Company_B|   25|       0.02|
|Company_B|   28|       0.03|
|Company_B|   30|       0.02|
|Company_A|  100|       null|
|Company_A|  103|       0.03|
|Company_A|  105|       0.02|
|Company_A|  107|       0.02|
+---------+-----+-----------+

答案 1 :(得分:1)

您可以使用window操作来实现此目的,理想情况下,您可以对具有idtimestamp的列进行排序。例如,我使用company作为排序键。

from pyspark.sql import functions as F
from pyspark.sql.window import Window

df = spark.read.csv("stock_price.txt", header=True, inferSchema=True)
price_window = Window.partitionBy("company").orderBy("company")
df = df.withColumn("prev_value", F.lag(df.price).over(price_window))
df = df.withColumn("diff", F.when(F.isnull(df.price - df.prev_value), 0).otherwise(df.price - df.prev_value))

+---------+-----+----------+----+
|  company|price|prev_value|diff|
+---------+-----+----------+----+
|Company_B|   23|      null|   0|
|Company_B|   25|        23|   2|
|Company_B|   28|        25|   3|
|Company_B|   30|        28|   2|
|Company_A|  100|      null|   0|
|Company_A|  103|       100|   3|
|Company_A|  105|       103|   2|
|Company_A|  107|       105|   2|
+---------+-----+----------+----+