web-dev-qa-db-ja.com

PySpark-UDFを使用して値のリストから列を追加する

値のリストに基づいて、PySparkデータフレームに列を追加する必要があります。

a= spark.createDataFrame([("Dog", "Cat"), ("Cat", "Dog"), ("Mouse", "Cat")],["Animal", "Enemy"])

各ペットの評価である評価と呼ばれるリストがあります。

rating = [5,4,1]

データフレームにRatingという列を追加する必要があります。

+------+-----+------+
|Animal|Enemy|Rating|
+------+-----+------+
|   Dog|  Cat|     5|
|   Cat|  Dog|     4|
| Mouse|  Cat|     1|
+------+-----+------+

私は次のことを行いましたが、評価列のリストの最初の値のみを返しています

def add_labels():
    return rating.pop(0)

labels_udf = udf(add_labels, IntegerType())

new_df = a.withColumn('Rating', labels_udf()).cache()

でる:

+------+-----+------+
|Animal|Enemy|Rating|
+------+-----+------+
|   Dog|  Cat|     5|
|   Cat|  Dog|     5|
| Mouse|  Cat|     5|
+------+-----+------+
3
Bryce Ramgovind

評価をrddに変換できます

rating = [5,4,1]
ratingrdd = sc.parallelize(rating)

次に、dataframerddに変換し、ratingrddの各値をrdd dataframeZipを使用して添付し、-を変換します。 zip形式のrdd再びdataframe

sqlContext.createDataFrame(a.rdd.Zip(ratingrdd).map(lambda x: (x[0][0], x[0][1], x[1])), ["Animal", "Enemy", "Rating"]).show()

それはあなたに与えるはずです

+------+-----+------+
|Animal|Enemy|Rating|
+------+-----+------+
|   Dog|  Cat|     5|
|   Cat|  Dog|     4|
| Mouse|  Cat|     1|
+------+-----+------+
2
Ramesh Maharjan

私は間違っているかもしれませんが、受け入れられた答えはうまくいかないと思います。 monotonically_increasing_id IDが一意で増加することを保証するだけであり、連続することは保証しません。したがって、2つの異なるデータフレームで使用すると、2つの非常に異なる列が作成される可能性が高く、結合はほとんど空を返します。

この回答からインスピレーションを得て https://stackoverflow.com/a/48211877/72253 同様の質問にすると、間違った回答を次のように変更できます。

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

a= sqlContext.createDataFrame([("Dog", "Cat"), ("Cat", "Dog"), ("Mouse", "Cat")],
                               ["Animal", "Enemy"])

a.show()

+------+-----+
|Animal|Enemy|
+------+-----+
|   Dog|  Cat|
|   Cat|  Dog|
| Mouse|  Cat|
+------+-----+



#convert list to a dataframe
rating = [5,4,1]
b = sqlContext.createDataFrame([(l,) for l in rating], ['Rating'])
b.show()

+------+
|Rating|
+------+
|     5|
|     4|
|     1|
+------+


a = a.withColumn("idx", F.monotonically_increasing_id())
b = b.withColumn("idx", F.monotonically_increasing_id())

windowSpec = W.orderBy("idx")
a = a.withColumn("idx", F.row_number().over(windowSpec))
b = b.withColumn("idx", F.row_number().over(windowSpec))

a.show()
+------+-----+---+
|Animal|Enemy|idx|
+------+-----+---+
|   Dog|  Cat|  1|
|   Cat|  Dog|  2|
| Mouse|  Cat|  3|
+------+-----+---+

b.show()
+------+---+
|Rating|idx|
+------+---+
|     5|  1|
|     4|  2|
|     1|  3|
+------+---+

final_df = a.join(b, a.idx == b.idx).drop("idx")

+------+-----+------+
|Animal|Enemy|Rating|
+------+-----+------+
|   Dog|  Cat|     5|
|   Cat|  Dog|     4|
| Mouse|  Cat|     1|
+------+-----+------+
1
Biggus

ratingリストはドライバーのメモリにあるのに対し、aデータフレームはエグゼキュータのメモリにあるため、実行しようとしていることは機能しません(udfはエグゼキュータでも機能します)。

次のように、キーをratingsリストに追加する必要があります。

ratings = [('Dog', 5), ('Cat', 4), ('Mouse', 1)]

次に、リストからratingsデータフレームを作成し、両方を結合して新しい列を追加します。

ratings_df = spark.createDataFrame(ratings, ['Animal', 'Rating'])
new_df = a.join(ratings_df, 'Animal')
0
Tw UxTLi51Nus