执行以下脚本时,我收到错误“int object is unsubscriptable”:
element.reduceByKey( lambda x , y : x[1]+y[1])
with element是一个键值RDD,值是一个元组。示例输入:
(A, (toto , 10))
(A, (titi , 30))
(5, (tata, 10))
(A, (toto, 10))
我理解reduceByKey
函数采用(K,V)元组并对所有值应用函数以获得reduce的最终结果。
与ReduceByKey Apache中给出的示例类似。
请帮忙吗?
答案 0 :(得分:2)
这是一个例子,将说明正在进行的事情。
让我们考虑一下您在列有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]
是一个整数,所以没有__getitem__
方法,因此你的错误。
通常,更好的方法(如下所示)是使用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
以下是另一种方法:
您可以在tuple
函数中创建reduce
,然后调用map
以提取所需的值。 (基本上颠倒了map
和reduce
的顺序。)
print(
element.reduceByKey(lambda u, v: (0,u[1]+v[1]))
.map(lambda x: (x[0], x[1][1]))
.collect()
)
[('A', 50), ('5', 10)]
备注强>
add_tuple_values()
会给你正确的输出。答案 1 :(得分:2)
另一种方法是使用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)]