2017-11-01 17 views
1

は、我々はデータフレームのアイリスを持っていると言います。変換火花データフレーム

import pyspark.sql.functions as F 
get_max_3 = F.udf(
    lambda x: sorted(x)[-3:] 
) 

agged = df.groupBy('species').agg(F.collect_list('sepal_width').alias('sepal_width')) 
agged = agged.withColumn('sepal_width', get_max_3('sepal_width')) 

+----------+---------------+ 
| species| sepal_width| 
+----------+---------------+ 
| virginica|[3.6, 3.8, 3.8]| 
|versicolor|[3.2, 3.3, 3.4]| 
| setosa|[4.1, 4.2, 4.4]| 
+----------+---------------+ 

、どのように私は、効率的に、長い形式(各行が1つの値に対応して、種ごとに3行を意味する)におけるデータフレームの中に、この背を向けるでしょうか?

collect_listを使用せずにこれを行う方法はありますか?

答えて

2

データフレームを長い形式に変換するには、explodeを使用できます。この方法を使用するには、しかし、あなたは、まずあなたのudfを修正する必要があり、それは正しい型を返す:

from pyspark.sql.types import * 
import pyspark.sql.functions as F 

get_max_3 = F.udf(lambda x: sorted(x)[-3:], ArrayType(DoubleType())) 

agged = agged.withColumn('sepal_width', get_max_3('sepal_width')) 
agged.withColumn('sepal_width', F.explode(F.col('sepal_width'))).show() 

+----------+-----------+ 
| species|sepal_width| 
+----------+-----------+ 
| virginica|  3.6| 
| virginica|  3.8| 
| virginica|  3.8| 
|versicolor|  3.2| 
|versicolor|  3.3| 
|versicolor|  3.4| 
| setosa|  4.1| 
| setosa|  4.2| 
| setosa|  4.4| 
+----------+-----------+ 

またはリストとして収集せずにして爆発、あなたはsepal_width列まず、次にフィルタをランク付けすることができますrank

df.selectExpr(
    "species", "sepal_width", 
    "row_number() over (partition by species order by sepal_width desc) as rn" 
).where(F.col("rn") <= 3).drop("rn").show() 
+----------+-----------+ 
| species|sepal_width| 
+----------+-----------+ 
| virginica|  3.8| 
| virginica|  3.8| 
| virginica|  3.6| 
|versicolor|  3.4| 
|versicolor|  3.3| 
|versicolor|  3.2| 
| setosa|  4.4| 
| setosa|  4.2| 
| setosa|  4.1| 
+----------+-----------+ 
関連する問題