[英]How to transform Array[(Double, Double)] into Array[Double] in Scala?
我正在使用Spark(v1.1.0)和Scala的MLlib来对应用于具有点(经度和纬度)的文件进行k均值聚类。 我的文件包含4个用逗号分隔的字段(最后两个是经度和纬度)。
这是使用Spark进行k均值聚类的示例: https : //spark.apache.org/docs/1.1.0/mllib-clustering.html
我要做的是读取HDFS中特定目录中文件的最后两个字段,将它们转换为RDD<Vector>
在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中运行它时,出现以下错误:
错误:方法值重载且带有替代项:(值:Array [Double])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>
,有什么建议吗?
密集向量有两种“工厂”方法:
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))
(您当然可以内联该代码,我在这里将其分开以专注于当前的问题)
val parsedData = data.map(s => Vectors.dense(s.split(',').flatMap(fields => Array(fields(2).toDouble,fields(3).toDouble))))
以前使用flatMap的建议是基于以下假设:您想映射.split(“,”)给定的数组元素-并且通过使用Array而不是Tuple2满足了类型。
.map / .flatMap函数接收到的参数是原始集合的元素,因此为了清楚起见,应将其命名为“ field”(singluar)。 调用fields(2)选择拆分的每个元素的第三个字符,因此会引起混乱。
如果您要查找的是.split(“,”)数组的第3个和第4个元素,则将其转换为Double:
s.split(",").drop(2).take(2).map(_.toDouble)
或者,如果您希望所有BUT都首先转换为Double(如果可能超过2个),则:
s.split(",").drop(2).map(_.toDouble)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.