如何在Spark中使用DenseVector作为键将groupByKey组为​​RDD?

时间:2015-07-16 08:43:55

标签: python apache-spark pyspark apache-spark-mllib

我创建了一个RDD,每个成员都是一个键值对,键为DenseVector,值为int。例如

[(DenseVector([3,4]),10),  (DenseVector([3,4]),20)]

现在我想按键k1分组:DenseVector([3,4])。我希望该行为能够对k110的密钥20的所有值进行分组。但我得到的结果是

[(DenseVector([3,4]), 10), (DenseVector([3,4]), 20)] 

而不是

[(DenseVector([3,4]), [10,20])]

如果我错过了什么,请告诉我。

相同的代码是:

#simplified version of code
#rdd1 is an rdd containing [(DenseVector([3,4]),10),  (DenseVector([3,4]),20)]
rdd1.groupByKey().map(lambda x : (x[0], list(x[1])))
print(rdd1.collect())

1 个答案:

答案 0 :(得分:3)

嗯,这是一个棘手的问题,简短的回答是你不能。要了解为什么您必须深入了解DenseVector实施。 DenseVector只是NumPy float64 ndarray

的包装器
>>> dv1 = DenseVector([3.0, 4.0])
>>> type(dv1.array)
<type 'numpy.ndarray'>
>>> dv1.array.dtype
dtype('float64')

由于NumPy ndarraysDenseVector不同,因此不可能以有意义的方式进行哈希处理,尽管有趣的是提供__hash__方法。有一个有趣的问题涉及这个问题(参见:numpy ndarray hashability)。

>>> dv1.array.__hash__() is None
False
>>> hash(dv1.array)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'numpy.ndarray'

DenseVector继承__hash__的{​​{1}}方法,它只是基于object(给定实例的内存地址):

id

不幸的是,这意味着具有相同内容的两个>>> id(d1) / 16 == hash(d1) True 具有不同的哈希值:

DenseVectors

你能做什么?最简单的方法是使用不可变的数据结构,它提供一致的>>> dv2 = DenseVector([3.0, 4.0]) >>> hash(dv1) == hash(dv2) False 实现,例如元组:

hash

注意:实际上,使用数组作为键很可能是一个坏主意。使用大量元素进行散列处理可能会非常昂贵而有用。不过,如果你真的需要这样的东西,Scala似乎工作得很好:

rdd.groupBy(lambda (k, v): tuple(k))