【问题标题】:How lambda function in takeOrdered function works in pySpark?takeOrdered 函数中的 lambda 函数如何在 pySpark 中工作?
【发布时间】:2015-06-12 15:07:25
【问题描述】:

我无法完全理解以下代码中 lambda 的行为:

rdd = sc.parallelize([5,3,1,2)]
rdd.takeOrdered(3,lambda s: -1*s)

据我了解,lambda 将操作应用于列表中的所有元素,所以我希望上面的代码返回

[-1,-2,-3]

但它返回了

[5,3,2]

我在这里错过了什么?

【问题讨论】:

  • 一个 lambda 只是一个创建函数对象的表达式。 takeOrdered 负责将其实际应用于任何事物。

标签: python lambda apache-spark pyspark


【解决方案1】:

https://spark.apache.org/docs/1.1.1/api/python/pyspark.rdd.RDD-class.html

takeOrdered(self, num, key=None) 从一个有序的 RDD 中获取 N 个元素 按升序或按可选键功能指定。

所以在您的示例中,您提供了一个订单功能。

【讨论】:

    【解决方案2】:

    rdd.takeOrdered 实际上接受一个比较器作为它的第二个参数。

    你想做的是这样的:

    rdd.map(lambda s: -1*s).takeOrdered(3)
    

    这将映射您的值,然后按顺序取前 3 个。

    老实说,我不确定 spark 对你传递的 lamda 做了什么。

    【讨论】:

    • 可选参数是关键函数,而不是比较器。它应用于列表的每个元素,以生成该元素应该排序的键。
    • 有趣,你是对的。与 java 和 scala 相比,这在 pyspark 中的行为似乎有所不同,后者的第二个参数分别是 Comparator 或 Ordering。不过,上面的代码会完成你想要的
    【解决方案3】:

    可能你想这样做

    rdd.takeOrdered(3, key = lambda s: (-1*s))

    【讨论】:

      【解决方案4】:

      可能更容易将 takeOrdered 的第二个参数 lambda 视为“密钥提取器”,因为它不对基础数据进行任何转换。

      在我们得到这个数字数组的简单情况下,键就是值

      rdd = sc.parallelize([5,3,1,2)]   
      rdd.takeOrdered(3, lambda x: x) #[1,2,3]
      

      或者,在您提交的代码中,项目按值的倒数排序(-5

      rdd.takeOrdered(3, lambda x: -x) #[5,3,2]
      

      当您将 lambda 提供给 takeOrdered 时,您所做的只是告诉它您希望它按什么排序。如果您想要额外的转换,它们必须在另一个步骤中发生。

      要返回您想要的输出,您可以将项目映射到它们的倒数,然后按原始值(倒数的倒数)对它们进行排序:

      rdd.map(lambda x: -x)\ #[-5,-3,-1,-2]
         .takeOrdered(3, lambda x: -x) #[-1,-2,-3]
      

      【讨论】:

        【解决方案5】:

        先尝试映射:

        rdd = sc.parallelize([5,3,1,2)]
        newRDD = rdd.map(lambda s: -1*s)
        

        然后返回或打印一个动作(地图是一个转换)...例如

        rdd.collect()
        

        然后,如果您想采用特定的数字或项目顺序(升序或降序),您可以尝试使用 takeOrdered("number of items you want," 您希望它们被采用的顺序(-1 reverse顺序)”。

        newRDD = (rdd
                   .map(lambda s: -1*s)
                   .takeOrdered(3, lambda s: -1*s))
        

        【讨论】:

          【解决方案6】:

          下面的意思是按降序获取前3个元素,lambda基本上是应用于ordering属性而不是最终结果。

          rdd.takeOrdered(3, key = lambda s: -s)

          以下方式按升序获取前3个元素:

          rdd.takeOrdered(3, key = lambda s: s)

          你想要做的是在 takeOrdered 之前使用 map 函数,map 函数是实际应用于列表中每个元素的,即 map 是用来修改列表中每个值的,产生所需的输出[-1, -2, -3]

          rdd = sc.parallelize([5,3,1,2])
          rdd.map(lambda s: -s).takeOrdered(3, key = lambda s: -s)
          

          【讨论】:

            【解决方案7】:

            它与 Python 中现有的 sorted 函数非常相似。查看此站点中有关“关键功能”的示例:https://wiki.python.org/moin/HowTo/Sorting

            您从[5, 3, 1, 2] 开始。

            假设密钥附加为[(5, -5), (3, -3), (1, -1), (2, -2)]

            然后,您按关键字按升序对其进行排序,得到:[(5, -5), (3, -3), (2, -2), (1, -1)]

            现在,忽略每对中的第二个元素(键):[5, 3, 2, 1]

            然后,选择前3项:[5, 3, 2]

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-06-30
              • 1970-01-01
              • 2021-07-01
              • 2014-12-31
              • 2012-02-01
              • 2020-01-28
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多