Python 使用reducebykey时出错:int对象不可订阅

Python 使用reducebykey时出错:int对象不可订阅,python,apache-spark,pyspark,Python,Apache Spark,Pyspark,执行以下脚本时,我收到一个错误“int对象不可订阅”: element.reduceByKey( lambda x , y : x[1]+y[1]) with元素是一个键值RDD,该值是一个元组。输入示例: (A, (toto , 10)) (A, (titi , 30)) (5, (tata, 10)) (A, (toto, 10)) 我知道reduceByKey函数接受(K,V)元组,并对所有值应用一个函数以获得reduce的最终结果。 如中给出的示例 有什么帮助吗?这里有一个例子可以说

执行以下脚本时,我收到一个错误“int对象不可订阅”:

element.reduceByKey( lambda x , y : x[1]+y[1])
with元素是一个键值RDD,该值是一个元组。输入示例:

(A, (toto , 10))
(A, (titi , 30))
(5, (tata, 10))
(A, (toto, 10))
我知道
reduceByKey
函数接受(K,V)元组,并对所有值应用一个函数以获得reduce的最终结果。 如中给出的示例


有什么帮助吗?

这里有一个例子可以说明发生了什么

让我们考虑一下,当你调用一个列表中的<代码>减少< /代码>时,使用一些函数<代码> f>代码>:

reduce(f, [a,b,c]) = f(f(a,b),c)
如果我们以您的示例为例,
f=lambda u,v:u[1]+v[1]
,则上述表达式分解为:

reduce(f, [a,b,c]) = f(f(a,b),c) = f(a[1]+b[1],c)
但是
a[1]+b[1]
是一个整数,因此没有
\uuu getitem\uuu
方法,因此您的错误

通常,更好的方法(如下所示)是使用
map()
首先以所需的格式提取数据,然后应用
reduceByKey()


包含您的数据的MCVE

element = sc.parallelize(
    [
        ('A', ('toto' , 10)),
        ('A', ('titi' , 30)),
        ('5', ('tata', 10)),
        ('A', ('toto', 10))
    ]
)
通过更复杂的reduce函数,您几乎可以获得所需的输出:

def add_tuple_values(a, b):
    try:
        u = a[1]
    except:
        u = a
    try:
        v = b[1]
    except:
        v = b
    return u + v

print(element.reduceByKey(add_tuple_values).collect())
但这会导致:

[('A', 50), ('5', ('tata', 10))]
为什么??因为键
'5'
只有一个值,所以没有什么可减少的

出于这些原因,最好先调用
map
。要获得所需的输出,您可以执行以下操作:

>>> print(element.map(lambda x: (x[0], x[1][1])).reduceByKey(lambda u, v: u+v).collect())
[('A', 50), ('5', 10)]

更新1

这里还有一种方法:

您可以在
reduce
函数中创建
tuple
s,然后调用
map
提取所需的值。(基本上颠倒了
map
reduce
的顺序)


注释

  • 如果每个键至少有2条记录,使用
    add\u tuple\u values()
    将为您提供正确的输出

    • 下面是一个例子,可以说明发生了什么

      让我们考虑一下,当你调用一个列表中的<代码>减少< /代码>时,使用一些函数<代码> f>代码>:

      reduce(f, [a,b,c]) = f(f(a,b),c)
      
      如果我们以您的示例为例,
      f=lambda u,v:u[1]+v[1]
      ,则上述表达式分解为:

      reduce(f, [a,b,c]) = f(f(a,b),c) = f(a[1]+b[1],c)
      
      但是
      a[1]+b[1]
      是一个整数,因此没有
      \uuu getitem\uuu
      方法,因此您的错误

      通常,更好的方法(如下所示)是使用
      map()
      首先以所需的格式提取数据,然后应用
      reduceByKey()


      包含您的数据的MCVE

      element = sc.parallelize(
          [
              ('A', ('toto' , 10)),
              ('A', ('titi' , 30)),
              ('5', ('tata', 10)),
              ('A', ('toto', 10))
          ]
      )
      
      通过更复杂的reduce函数,您几乎可以获得所需的输出:

      def add_tuple_values(a, b):
          try:
              u = a[1]
          except:
              u = a
          try:
              v = b[1]
          except:
              v = b
          return u + v
      
      print(element.reduceByKey(add_tuple_values).collect())
      
      但这会导致:

      [('A', 50), ('5', ('tata', 10))]
      
      为什么??因为键
      '5'
      只有一个值,所以没有什么可减少的

      出于这些原因,最好先调用
      map
      。要获得所需的输出,您可以执行以下操作:

      >>> print(element.map(lambda x: (x[0], x[1][1])).reduceByKey(lambda u, v: u+v).collect())
      [('A', 50), ('5', 10)]
      

      更新1

      这里还有一种方法:

      您可以在
      reduce
      函数中创建
      tuple
      s,然后调用
      map
      提取所需的值。(基本上颠倒了
      map
      reduce
      的顺序)


      注释

      • 如果每个键至少有2条记录,使用
        add\u tuple\u values()
        将为您提供正确的输出

        • 另一种方法是使用数据帧

          rdd = sc.parallelize([('A', ('toto', 10)),('A', ('titi', 30)),('5', ('tata', 10)),('A', ('toto', 10))])
          rdd.map(lambda (a,(b,c)): (a,b,c)).toDF(['a','b','c']).groupBy('a').agg(sum("c")).rdd.map(lambda (a,c): (a,c)).collect()
          
          >>>[(u'5', 10), (u'A', 50)]
          

          另一种方法是使用Dataframe

          rdd = sc.parallelize([('A', ('toto', 10)),('A', ('titi', 30)),('5', ('tata', 10)),('A', ('toto', 10))])
          rdd.map(lambda (a,(b,c)): (a,b,c)).toDF(['a','b','c']).groupBy('a').agg(sum("c")).rdd.map(lambda (a,c): (a,c)).collect()
          
          >>>[(u'5', 10), (u'A', 50)]
          

          您想要什么输出?问题是
          x[1]+y[1]
          是一个int,而不是元组(这是
          reduceByKey
          在下一次迭代中所期望的。期望的输出是
          (a,50)(5,10)
          ,但是为什么
          reduceByKey
          应该在下一次迭代中期望一个元组呢?它应该保持相同类型的值减少吗?你想要什么输出?问题是
          x[1]+y[1]
          是一个int,而不是元组(这是
          reduceByKey
          在下一次迭代中期望的。期望的输出是
          (a,50)(5,10)
          ,但为什么
          reduceByKey
          应该在下一次迭代中期望一个元组?它应该保持相同类型的值被缩减吗?