PySpark的reduceByKey中使用列表作为键

8
我正在尝试在格式为(([a,b,c], 1), ([a,b,c], 1), ([a,d,b,e], 1), ...的数据上调用pyspark的reduceByKey函数。
似乎pyspark不接受数组作为普通键值减少,只需应用.reduceByKey(add)。我已经尝试将数组转换为字符串,通过.map((x,y): (str(x),y)),但这样做不起作用,因为将字符串后处理回数组太慢了。
有没有办法让pyspark使用数组作为键或使用另一个函数快速将字符串转换回数组?
以下是相关的错误代码:
  File "/home/jan/Documents/spark-1.4.0/python/lib/pyspark.zip/pyspark/shuffle.py", line 268, in mergeValues
    d[k] = comb(d[k], v) if k in d else creator(v)
TypeError: unhashable type: 'list'
    enter code here

总结:

输入:x =[([a,b,c], 1), ([a,b,c], 1), ([a,d,b,e], 1), ...]

期望输出:y =[([a,b,c], 2), ([a,d,b,e], 1),...] 这样我就可以通过 y[0][0][0] 访问 a,并通过 y[0][1] 访问 2

1个回答

11
尝试这个:
rdd.map(lambda (k, v): (tuple(k), v)).groupByKey()

由于Python列表是可变的,这意味着它们不能被哈希(不提供__hash__方法):

>>> a_list = [1, 2, 3]
>>> a_list.__hash__ is None
True
>>> hash(a_list)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

相较而言,元组是不可变的,并且提供了__hash__方法的实现:

>>> a_tuple = (1, 2, 3)
>>> a_tuple.__hash__ is None
False
>>> hash(a_tuple)
2528502973977326415

因此,可以将其用作键。同样,如果您想使用唯一值作为键,则应使用frozenset
rdd.map(lambda (k, v): (frozenset(k), v)).groupByKey().collect()

使用 set 命令的替代方法。

# This will fail with TypeError: unhashable type: 'set'
rdd.map(lambda (k, v): (set(k), v)).groupByKey().collect()

谢谢,这对我理解Spark的整体有很大帮助。 - Peter Doro
不用谢。顺便说一下,这并不是特定于Spark的。当你使用普通的Python dictssets时,同样适用。 - zero323

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接