web-dev-qa-db-ja.com

pysparkのリスト内のさまざまなデータフレーム列を合計する正しい方法は何ですか?

sparkデータフレーム内の異なる列を合計したい。

コード

from pyspark.sql import functions as F
cols = ["A.p1","B.p1"]
df = spark.createDataFrame([[1,2],[4,89],[12,60]],schema=cols)

# 1. Works
df = df.withColumn('sum1', sum([df[col] for col in ["`A.p1`","`B.p1`"]]))

#2. Doesnt work
df = df.withColumn('sum1', F.sum([df[col] for col in ["`A.p1`","`B.p1`"]]))

#3. Doesnt work
df = df.withColumn('sum1', sum(df.select(["`A.p1`","`B.p1`"])))

なぜ#2にアプローチしないのですか。 &#3。動作していませんか?私はSpark 2.2

4
GeorgeOfTheRF

なぜなら、

# 1. Works
df = df.withColumn('sum1', sum([df[col] for col in ["`A.p1`","`B.p1`"]]))

ここでは、入力として反復可能であるpython組み込みの合計関数を使用しているため、機能します。 https://docs.python.org/2/library/functions.html #sum

#2. Doesnt work
df = df.withColumn('sum1', F.sum([df[col] for col in ["`A.p1`","`B.p1`"]]))

ここでは、入力として列を受け取るpyspark sum関数を使用していますが、行レベルで取得しようとしています。 http://spark.Apache.org/docs/latest/api/python/pyspark.sql.html#pyspark.sql.functions.sum

#3. Doesnt work
df = df.withColumn('sum1', sum(df.select(["`A.p1`","`B.p1`"])))

ここで、df.select()はデータフレームを返し、データフレームを合計しようとします。この場合、行ごとに繰り返し、合計を適用する必要があると思います。

8
Suresh

TL; DRbuiltins.sumは問題ありません。


あなたのフォロー コメント

ネイティブpython sum()を使用しても、spark最適化のメリットはありません。したがって、sparkの方法は何ですか?

および

これはpypark関数ではないため、spark rightから完全に恩恵を受けることはありません。

あなたが間違った仮定をしていることがわかります。

問題を分解してみましょう:

[df[col] for col in ["`A.p1`","`B.p1`"]]

Columnsのリストを作成します:

[Column<b'A.p1'>, Column<b'B.p1'>]

それをiterableと呼びましょう。

sumは、このリストの要素を取得して__add__メソッド(+)を呼び出すことにより、出力を減らします。命令型の同等物は次のとおりです。

accum = iterable[0]
for element in iterable[1:]:
    accum = accum + element

これにより、Columnが得られます:

Column<b'(A.p1 + B.p1)'>

これは呼び出すことと同じです

df["`A.p1`"] + df["`B.p1`"]

データは変更されておらず、評価すると、すべてのSpark最適化の恩恵を受けています。

3
Alper t. Turker