pyspark在udf中使用数据框

时间:2018-05-01 20:18:21

标签: apache-spark pyspark pyspark-sql

我有两个数据框import angular from "angular"; export default angular.module("practice", []).component("app", { template: "<div>This needs to show up!!</div>" });

<multipart-config>
<!– 50MB max –>
<max-file-size>52428800</max-file-size>
<max-request-size>52428800</max-request-size>
<file-size-threshold>0</file-size-threshold>
</multipart-config>

df1

+---+---+----------+
|  n|val| distances|
+---+---+----------+
|  1|  1|0.27308652|
|  2|  1|0.24969208|
|  3|  1|0.21314497|
+---+---+----------+

我想向名为df2的{​​{1}}添加一个新列,该列将包含+---+---+----------+ | x1| x2| w| +---+---+----------+ | 1| 2|0.03103427| | 1| 4|0.19012526| | 1| 10|0.26805446| | 1| 8|0.26825935| +---+---+----------+ df1的{​​{1}}值的总和

我尝试使用udf,但显然从不同的数据框中选择是行不通的,因为值应该在计算之前确定

gamma

有没有办法在不使用周期的情况下使用wdf2进行此操作?

1 个答案:

答案 0 :(得分:1)

您无法在udf内引用DataFrame。正如您所提到的,此问题最好使用join来解决。

IIUC,您正在寻找类似的内容:

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

df1.alias("L").join(df2.alias("R"), (df1.n == df2.x1) | (df1.n == df2.x2), how="left")\
    .select("L.*", F.sum("w").over(Window.partitionBy("n")).alias("gamma"))\
    .distinct()\
    .show()
#+---+---+----------+----------+
#|  n|val| distances|     gamma|
#+---+---+----------+----------+
#|  1|  1|0.27308652|0.75747334|
#|  3|  1|0.21314497|      null|
#|  2|  1|0.24969208|0.03103427|
#+---+---+----------+----------+

或者如果您对pyspark-sql语法更加熟悉,可以注册临时表并执行:

df1.registerTempTable("df1")
df2.registerTempTable("df2")

sqlCtx.sql(
    "SELECT DISTINCT L.*, SUM(R.w) OVER (PARTITION BY L.n) AS gamma "
    "FROM df1 L LEFT JOIN df2 R ON L.n = R.x1 OR L.n = R.x2"
).show()
#+---+---+----------+----------+
#|  n|val| distances|     gamma|
#+---+---+----------+----------+
#|  1|  1|0.27308652|0.75747334|
#|  3|  1|0.21314497|      null|
#|  2|  1|0.24969208|0.03103427|
#+---+---+----------+----------+

<强>解释

在这两种情况下,我们都df1 df2df1。这将保留df2中的所有行,无论是否匹配。

join子句是您在问题中指定的条件。因此x1x2n等于n的所有行都将被加入。

接下来选择左表中的所有行加上我们分组(分区依据)w并将n的值相加。对于INSERT INTO Table3 SELECT * FROM Table1; INSERT INTO Table3 SELECT * FROM Table2; 的每个值,这将获得与连接条件匹配的所有行的总和。

最后,我们只返回不同的行以消除重复。