我有一个带有日期,ID(比方说一个城市)和两列温度的数据框(在我的实际数据框中,我有一打列要计算)。
我想对给定窗口的温度进行“排序”。我希望此排名从0(窗口的最低温度)到100(同一窗口的最高温度)缩放。窗口必须是对称的(这意味着我要考虑之前和之后的几天)。我的测试数据框如下所示:
+-----------+-------+-----------------+-----------------+
|DATE_TICKET|ID_SITE|MAX_TEMPERATURE_C|MIN_TEMPERATURE_C|
+-----------+-------+-----------------+-----------------+
| 2017-03-24| 001| 22| 10|
| 2017-03-25| 001| 25| 15|
| 2017-03-26| 001| 31| 19|
| 2017-03-27| 001| 29| 18|
| 2017-03-28| 001| 30| 16|
| 2017-03-29| 001| 25| 17|
| 2017-03-30| 001| 24| 16|
| 2017-03-24| 002| 18| 12|
| 2017-03-25| 002| 17| 11|
| 2017-03-27| 002| 15| 7|
| 2017-03-28| 002| 12| 5|
| 2017-03-29| 002| 8| 3|
| 2017-03-30| 002| 10| 1|
| 2017-03-31| 002| 15| 4|
| 2017-03-24| 003| 18| 7|
| 2017-03-26| 003| 22| 11|
| 2017-03-27| 003| 27| 12|
| 2017-03-28| 003| 29| 15|
| 2017-04-01| 003| 31| 16|
| 2017-04-04| 003| 34| 22|
+-----------+-------+-----------------+-----------------+
要重新创建我的数据,可以使用以下代码:
data = {'DATE_TICKET': ['2017-03-24','2017-03-25','2017-03-26','2017-03-27','2017-03-28','2017-03-29','2017-03-30',
'2017-03-24','2017-03-25','2017-03-27','2017-03-28','2017-03-29','2017-03-30','2017-03-31',
'2017-03-24','2017-03-26','2017-03-27','2017-03-28','2017-04-01','2017-04-04'],
'ID_SITE': ['001','001','001','001','001','001','001','002','002','002','002','002','002','002','003','003','003','003','003','003'],
'MAX_TEMPERATURE_C': [22,25,31,29,30,25,24,18,17,15,12,8,10,15,18,22,27,29,31,34],
'MIN_TEMPERATURE_C' : [10,15,19,18,16,17,16,12,11,7,5,3,1,4,7,11,12,15,16,22]}
df = pd.DataFrame(data)
ddf = ctx.createDataFrame(df)
ddf = ddf.withColumn('DATE_TICKET', ddf['DATE_TICKET'].cast('date'))
此刻我的代码如下:
import pandas as pd
import pyspark
import pyspark.sql.functions as F
import pyspark.sql.types as T
from pyspark.sql.window import Window
from pyspark.sql.types import FloatType
window_size = 2
target = int((window_size)-0.5)
w = Window.partitionBy("ID_SITE").orderBy("DATE_TICKET").rowsBetween(-(window_size), window_size)
median_udf = F.udf(lambda x: float(np.median(x)), FloatType())
rank_udf = F.udf(lambda x: pd.cut(x, 101, include_lowest=True, labels=list(range(0,101)))[target])
ddf.withColumn("list", F.collect_list("MAX_TEMPERATURE_C").over(w)) \
.withColumn("rolling_median", median_udf("list")).show(truncate = False)
这与'median_udf'函数一起工作(顺便说一句,我是从stackoverflow上的另一篇文章中复制/粘贴的)。但是此功能不能满足我的期望。
我想使用rank_udf函数,当我将其应用于单个列表时,它可以正常工作。它对给定窗口的所有值进行排名,并返回一个我感兴趣的单个值,即中间的一个。
例如:
data = [22,25,31,29,31,34,26,21]
target = int((len(data)/2)-0.5)
pd.cut(data, 101, include_lowest=True, labels=list(range(0,101)))[target]
但是:
我尝试使用pyspark.ml.feature中的Bucketizer或QuantileDiscretizer之类的功能,但是我无法使其正常工作...
(PS:是的,我确实知道它并不是真正的百分位数,因为我使用的是101个垃圾箱而不是100个垃圾箱)
(PPS:如果您需要更多上下文/信息,我将编辑此帖子。)