pyspark中函数的输入和输出

时间:2016-09-17 08:09:17

标签: python apache-spark pyspark

我想在pyspark中获得关于输入语法的一些教训。

我的平台如下。

Red Hat Enterprise Linux Server release 6.8 (Santiago)
spark version 1.6.2
python 2.6

我在模块 basic_lib.py 中定义了def,如下所示。

def selectRowByTimeStamp(x,y):
    if x._1 > y._1:
        return x
    return y

以下是我的主要代码片段

  df2 = df2.map(lambda x: (x._2, x))
  rdd = df2.reduceByKey(basic_lib.selectRowByTimeStamp)

为什么上面的 basic_lib.selectRowByTimeStamp 没有清楚地工作 指定输入参数?

例如,下面的内容更容易理解。

var1 = 1
var2 = 2

rdd = df2.reduceByKey(basic_lib.selectRowByTimeStamp(var1, var2))

1 个答案:

答案 0 :(得分:2)

看起来你对lambda表达式的目的究竟是什么感到有些困惑。通常,Python中的lambda表达式用于创建匿名的单表达式函数。除此之外,就我们所关心的而言,与您定义的任何其他功能没有什么不同。引用文档:

  

可以使用lambda关键字创建小的匿名函数。 (...)Lambda函数可以在需要函数对象的任何地方使用。 从语义上讲,它们只是正常函数定义的语法糖。

由于lambda函数在Python中并不特别,所以在PySpark中没有特别之处(好吧,由于它们的范围,它们可能需要一些序列化技巧,但它只是关于它们的范围)。无论函数是否由lambda定义(或者甚至是函数*),Spark都以完全相同的方式应用它。所以当你打电话时:

df2.map(lambda x: (x._2, x))

简单地评估lambda表达式,map接收的只是另一个函数对象。如果您先分配,则不会有所不同:

foo = lambda x: (x._2, x)  # Yup, this is against style guide (PEP 8)

或创建一个独立的功能:

def bar(x):
    return x._2, x 

在所有三种情况下,函数对象在功能上几乎相同:

import dis

dis.dis(foo)
##   1           0 LOAD_FAST                0 (x)
##               3 LOAD_ATTR                0 (_2)
##               6 LOAD_FAST                0 (x)
##               9 BUILD_TUPLE              2
##              12 RETURN_VALUE

dis.dis(bar)
##   2           0 LOAD_FAST                0 (x)
##               3 LOAD_ATTR                0 (_2)
##               6 LOAD_FAST                0 (x)
##               9 BUILD_TUPLE              2
##              12 RETURN_VALUE

dis.dis(lambda x: (x._2, x))
##   1           0 LOAD_FAST                0 (x)
##               3 LOAD_ATTR                0 (_2)
##               6 LOAD_FAST                0 (x)
##               9 BUILD_TUPLE              2
##              12 RETURN_VALUE

另一方面,如果输入是DataFrame,则使用Spark SQL解决此问题会更有效。此外,最好在使用rdd之前提取map以确保向前兼容性。最后Row只是一个元组。

你最好能够:

df.groupBy("_2").max()

但如果你真的想使用RDD API:

df.select("_2", "_1").rdd.reduceByKey(max)

*实际上,任何可调用对象都可以工作,只要它接受给定的参数即可。例如(这里没有意义)你可以用如下定义的类的对象替换函数:

class FooBar(object):
    def __call__(self, x):
        return x._2, x

df2.rdd.map(FooBar())