Python 使用reducebykey时出错:int对象不可订阅
执行以下脚本时,我收到一个错误“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的最终结果。 如中给出的示例 有什么帮助吗?这里有一个例子可以说
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
应该在下一次迭代中期望一个元组?它应该保持相同类型的值被缩减吗?