如何在Scala中将Array [(Double,Double)]转换为Array [Double]?

时间:2014-12-06 12:19:16

标签: scala apache-spark k-means apache-spark-mllib

我正在使用Spark的MLlib(v1.1.0)和Scala来执行应用于具有点(经度和纬度)的文件的k均值聚类。 我的文件包含4个以逗号分隔的字段(最后两个是经度和纬度)。

这里,它是使用Spark进行k-means聚类的一个例子: https://spark.apache.org/docs/1.1.0/mllib-clustering.html

我想要的是读取我在HDFS中特定目录中的文件的最后两个字段,将它们转换为RDD<Vector> o在KMeans类中使用此方法: train(RDD<Vector> data, int k, int maxIterations)

这是我的代码:

val data = sc.textFile("/user/test/location/*") val parsedData = data.map(s => Vectors.dense(s.split(',').map(fields => (fields(2).toDouble,fields(3).toDouble))))

但是当我在spark-shell中运行时,我收到以下错误:

  

错误:使用替代方法重载方法值密集:(值:   数组[双])org.apache.spark.mllib.linalg.Vector(firstValue:   Double,otherValues:Double *)org.apache.spark.mllib.linalg.Vector   不能应用于(Array [(Double,Double)])

所以,我不知道如何将我的Array [(Double,Double)]转换为Array [Double]。也许有另一种方法来阅读这两个字段并将它们转换为RDD<Vector>,任何建议?

3 个答案:

答案 0 :(得分:1)

密集载体有两种“工厂”方法:

def dense(values: Array[Double]): Vector
def dense(firstValue: Double, otherValues: Double*): Vector

虽然上面提供的类型是Array[Tuple2[Double,Double]],因此不匹配:
(提取上面的逻辑:)

val parseLineToTuple: String => Array[(Double,Double)] = s => s=> s.split(',').map(fields => (fields(2).toDouble,fields(3).toDouble))

这里需要的是从输入String中创建一个新的Array,如下所示:(再次只关注特定的解析逻辑)

val parseLineToArray: String => Array[Double] = s=> s.split(",").flatMap(fields => Array(fields(2).toDouble,fields(3).toDouble)))

将其整合到原始代码中可以解决问题:

val data = sc.textFile("/user/test/location/*")
val vectors = data.map(s => Vectors.dense(parseLineToArray(s))

(你当然可以内联代码,我把它分开来专注于手头的问题)

答案 1 :(得分:1)

val parsedData = data.map(s => Vectors.dense(s.split(',').flatMap(fields => Array(fields(2).toDouble,fields(3).toDouble))))

答案 2 :(得分:1)

使用flatMap的先前建议是基于这样的假设:您希望映射.split(&#34;,&#34;)给出的数组元素 - 并通过使用Array提供以满足类型而不是Tuple2。

.map / .flatMap函数收到的参数是原始集合的一个元素,因此应命名为&#39; field&#39; (singluar)为了清楚起见。调用字段(2)选择分割中每个元素的第3个字符 - 因此是混淆的来源。

如果您追求的是.split(&#34;,&#34;)数组的第3和第4个元素,则转换为Double:

s.split(",").drop(2).take(2).map(_.toDouble)

或者如果你想要所有BUT,则第一个字段转换为Double(如果可能超过2个):

s.split(",").drop(2).map(_.toDouble)