我想在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))
答案 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())