【问题标题】:PySpark Row objects: accessing row elements by variable namesPySpark Row 对象:通过变量名访问行元素
【发布时间】:2016-07-10 10:01:58
【问题描述】:

可以使用点符号访问 PySpark Row 元素:给定 r= Row(name="Alice", age=11),可以分别使用 r.namer.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'))

然而,在每一行上调用toDict() 似乎效率很低。有没有更好的办法?

【问题讨论】:

  • > 也许是filter 你能举个例子吗,我不知道如何使用filter
  • 对不起我的错误,但是我的小解释的第二部分是正确的。 map 是最快的作业之一,因为它很容易并行化。
  • 我知道map 很好。我想让它变得更好,但不必将每一行都转换为字典
  • 抱歉打错了。我想让它变得更好 BY 不必将每一行都转换为字典

标签: python apache-spark pyspark


【解决方案1】:

在 Python 中,如果某些东西有效,那就没有什么魔力了。当某些东西起作用时,比如这里的点语法,它意味着一个可预测的事件链。特别是你可以期待 __getattr__ 方法会被调用:

from pyspark.sql import Row

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

a_row.__getattr__("foo")
## 1
a_row.__getattr__("bar")
True

Row 还覆盖 __getitem__ 以具有相同的行为:

a_row.__getitem__("foo")
## 1

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

a_row["bar"]
## True

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

一般来说,你应该避免这样的调用:

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

【讨论】:

  • > 每个调用都是 O(N) N 是列数吗?就我而言,这非常小,我怀疑.asDict() 附带的内存分配/垃圾收集将需要更多时间。我想我只需要测量时间。谢谢
  • 有趣的是,在我问这个问题的前一天,我写了一堆包装器并实现了几个__getattr____getitem__函数。然后我切换了上下文并忘记了它们:-)
  • 您可能是对的,尽管我会避免在 Spark SQL 中使用 Python 映射器,并且如果您在执行映射器之前明确使用此提取值。
【解决方案2】:
python_var_list =[ [ele[0],ele[1]] for ele in r]

上面的代码行应该为 r 中的每一行访问 pyspark 中的行元素

【讨论】:

  • 嘿 Rajesh,欢迎来到 stackoverflow。我使用 crtl K 将您的代码放入代码块中(选择代码时)。它非常有用,可以帮助其他用户阅读和复制您的解决方案。
猜你喜欢
  • 2019-01-26
  • 1970-01-01
  • 1970-01-01
  • 2014-04-25
  • 2021-05-21
  • 1970-01-01
  • 2011-11-08
  • 2022-07-28
  • 1970-01-01
相关资源
最近更新 更多