Spark Mllib kmeans示例,使用数据帧而不是textFile

时间:2015-07-13 05:14:12

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

我试图在浮点数的数据帧上运行Spark(1.3.1)Mllib k-means聚类。 我跟随Spark提供的群集示例

https://spark.apache.org/docs/1.3.1/mllib-clustering.html

但是,我使用的是由一列双打组成的数据帧(为简单起见),而不是文本文件。根据Mllib文档,我需要将其转换为Kmeans函数的向量。到目前为止我有这个

    import org.apache.spark.mllib.linalg.Vectors
    val parsedData = data.map(s => Vectors.dense(s(0))).cache()

我收到错误

error: overloaded method value dense with alternatives:
(values: Array[Double])org.apache.spark.mllib.linalg.Vector and
(firstValue: Double,otherValues: Double*)org.apache.spark.mllib.linalg.Vector
cannot be applied to (Any)
val parsedData = sample2.map(s => Vectors.dense(s(1))).cache()
                                          ^

有更好的方法吗?

我看过这篇类似的帖子,但我发现它不够相似: How to turn a known structured RDD to Vector 这一个How to convert org.apache.spark.rdd.RDD[Array[Double]] to Array[Double] which is required by Spark MLlib 处理文本数据

2 个答案:

答案 0 :(得分:1)

由于import org.apache.spark.sql.Row可以存储任何类型的值,因此apply方法具有以下签名:

 def apply(i: Int): Any 

Vectors.dense期望Double作为参数。有几种方法可以解决这个问题。让我们假设您要从列x中提取值。首先,您可以通过Row构造函数进行模式匹配:

data.select($"x").map {
    case  Row(x: Double) => Vectors.dense(x)
}

如果您更喜欢位置方法,则使用模式匹配而不是apply:

返回的值
data.select($"x").map(row => row(0) match {
    case x: Double => Vectors.dense(x)
})

最后,您可以使用toDouble方法:

data.select($"x").map(r => Vectors.dense(r.getDouble(0)))

select部分是可选的,但它可以更轻松地对一行进行模式匹配,并保护您免受一些天真的错误,例如将错误的索引传递给get

如果想要逐个提取更多列,那么逐行可能会很麻烦。在这种情况下,这样的事情可能很有用:

data.select($"x", $"y", $"z").map(r => Vectors.dense(
    r.toSeq.map({ case col: Double => col }).toArray)
)

答案 1 :(得分:1)

怎么样:

val parsedData = data.rdd.map(s => Vectors.dense(s.getDouble(0))).cache()

如果数据是单列双精度数据帧,那么这应该有效。 如果您的数据框中有更多列,则只需添加更多内容,例如:

val parsedData = data.rdd.map(s => Vectors.dense(s.getDouble(0),s.getDouble(1))).cache()