PySpark行对象:通过变量名称访问行元素

Dav*_*d D 3 python apache-spark pyspark

可以Row使用点符号来访问PySpark 元素:给定r= Row(name="Alice", age=11),可以分别使用r.name或来获取名称或年龄r.age。当需要获取其名称存储在变量中的元素时会发生什么element?一种选择是做r.toDict()[element]。但是,考虑一种情况,我们有一个很大的空间DataFrame,并且希望在该数据帧的每一行上映射一个函数。我们当然可以做类似的事情

def f(row, element1, element2):
    row = row.asDict()
    return ", ".join(str(row[element1]), str(row[element2]))

result = dataframe.map(lambda row: f(row, 'age', 'name'))
Run Code Online (Sandbox Code Playgroud)

但是,似乎toDict()每一行的调用效率都非常低。有没有更好的办法?

zer*_*323 6

与往常一样,如果某些方法有效,那么那里就没有魔术了。当某些东西起作用时,例如此处的点语法,就意味着可预测的事件链。特别是,您可以期望该__getattr__方法将被调用:

from pyspark.sql import Row

a_row = Row(foo=1, bar=True)

a_row.__getattr__("foo")
## 1
a_row.__getattr__("bar")
True
Run Code Online (Sandbox Code Playgroud)

行也将覆盖__getitem__以具有相同的行为:

a_row.__getitem__("foo")
## 1
Run Code Online (Sandbox Code Playgroud)

这意味着您可以使用方括号表示法:

a_row["bar"]
## True
Run Code Online (Sandbox Code Playgroud)

问题是效率不高。每个调用都是O(N),因此dict如果您有宽行和多个调用,则一次转换可以提高效率。

通常,您应该避免这样的调用:

  • 使用UDF效率不高,但总体上更清洁
  • 使用内置SQL表达式应优先于 map
  • 你不应该直接映射DataFrame。它很快就会被弃用。