2

Spark の MLlib (v1.1.0) と Scala を使用して、ポイント (経度と緯度) を含むファイルに k-means クラスタリングを適用しています。私のファイルには、コンマで区切られた 4 つのフィールドが含まれています (最後の 2 つは経度と緯度です)。

これは、Spark を使用した k-means クラスタリングの例です: https://spark.apache.org/docs/1.1.0/mllib-clustering.html

私がやりたいことは、HDFS の特定のディレクトリにあるファイルの最後の 2 つのフィールドを読み取り、それらをRDD<Vector>KMeans クラスで次のメソッドを使用する o に変換することです。 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] に変換する方法がわかりません。2 つのフィールドを読み取って に変換する別の方法があるかもしれませんがRDD<Vector>、何か提案はありますか?

4

3 に答える 3

1
val parsedData = data.map(s => Vectors.dense(s.split(',').flatMap(fields => Array(fields(2).toDouble,fields(3).toDouble))))
于 2014-12-07T10:18:50.670 に答える
1

密なベクトルには 2 つの「ファクトリー」メソッドがあります。

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))

ここで必要なのは、次のように、入力文字列から新しい配列を作成することです: (ここでも、特定の解析ロジックのみに焦点を当てています)

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))

(もちろん、そのコードをインライン化することもできます。目前の問題に焦点を当てるためにここで分けました)

于 2014-12-06T12:34:47.920 に答える
1

flatMap を使用した以前の提案は、.split(",") で指定された配列の要素をマップしたいという前提に基づいており、Tuple2 の代わりに Array を使用して型を満たすために提供されました。

.map/.flatMap 関数が受け取る引数は元のコレクションの要素であるため、わかりやすくするために「フィールド」(単数) という名前にする必要があります。fields(2) を呼び出すと、分割の各要素の 3 番目の文字が選択されるため、混乱の元になります。

Double に変換された .split(",") 配列の 3 番目と 4 番目の要素を求めている場合:

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

または、Double に変換された最初のフィールド以外のすべてが必要な場合 (2 つ以上ある場合):

s.split(",").drop(2).map(_.toDouble)
于 2014-12-08T07:35:28.407 に答える