pyspark根据ID计算四分位数,并根据四分位数范围进行分类

时间:2018-07-24 20:13:34

标签: python pyspark apache-spark-sql pyspark-sql

我正在使用pyspark 1.5.2。我有一个带有列“ ID”和“高度”的pyspark数据框,如下所示:

|           ID1|           ID2|       height|
---------------------------------------------
|             1|           000|           44|
|             2|           000|         72.9|
|             3|           000|           89|
|             4|           000|         45.5|
|             5|           000|         52.3|
|             6|           000|         87.9|
|             7|           000|         63.1|
|             8|           000|         26.1|
|             9|           000|           97|
|            10|           000|          120|
|            11|           000|           99|
|            12|           000|           96|
|            13|           000|         36.5|
|            14|           000|            0|
|            15|           001|           48|
|            16|           001|        152.1|
|            17|           001|         72.2|
|            18|           001|         21.5|
|            19|           001|           94|
|            20|           001|          220|
+--------------+--------------+-------------+

我要计算每个“ ID2”的高度四分位数,并根据以下标准将其分为高,中或短四分之三:

Short: All height < Q1
Medium: All height within inclusive inter-quartile range (IQR) Q3-Q1
Tall: All height > Q3

我正在研究pyspark.sql模块,并找到了summary()函数,通过该函数可以计算四分位数范围,但它不适用于基于“ ID2”列的groupby。最终结果将是:

|       ID1 |     Height |
-------------------------
|          1|        Tall|
|          2|       Short|
|          3|      Medium|  and so on

我该怎么做?有更好的方法还是更简单的方法?

对此我还很陌生,将不胜感激!

提前谢谢!

2 个答案:

答案 0 :(得分:1)

在处理函数中传递您的输入数据框,它将按照作者的意图返回输出数据框。 分位数功能会返回该范围内的两个值,并重新插入原始数据帧。然后可以在顶部运行比较器。

import pandas as pd
import numpy as np

def quantile(x):
    x['first']= np.percentile(x['height'], 25)
    x['third']= np.percentile(x['height'], 75)
    return  x

def process(input_df):
    grouped_df = input_df.groupby(['ID2']).apply(quantile)
    grouped_df.loc[(grouped_df.height >= grouped_df.first) & (grouped_df.height <= grouped_df.third), 'result'] = 'Medium'
    grouped_df.loc[(grouped_df.height < grouped_df.first) , 'result'] = 'Short'
    grouped_df.loc[ (grouped_df.height > grouped_df.third),'result'] = 'Tall'
    return grouped_df


main_df = pd.read_csv('sample.csv')
print process(main_df)

答案 1 :(得分:1)

这是一种使用pyspark 1.5.2的无熊猫方法。 “ input_df”是此处的原始数据帧:

input_df.registerTempTable("input_df")
quartile_df = sqlContext.sql("select id2, percentile_approx(cast(height as decimal), 0.25) as Q1_value, percentile_approx(cast(height as decimal), 0.5) as Q2_value, percentile_approx(cast(height as decimal), 0.75) as Q3_value from input_df group by id2")
input_df=input_df.join(quartile_df, input_df.id2 == quartile_df.id2, 'left_outer')
input_df.select(F.when(input_df.height < input_df.Q1_value, 'short').when(input_df.height.between(input_df.Q1_value, input_df.Q3_value), 'medium').when(input_df.height > input_df.Q3_value, 'tall').alias('height_tag')).show()

以上代码基本上将input_df注册为临时表,并允许通过SQL查询。在查询中,使用percentile_approx给出Q1,Q2和Q3,分别为25%,50%和75%,最终将它们与原始数据帧结合在一起。在最终的LOC中,“ height”的每个值都根据条件分为短,中或高。

希望这会有所帮助