Spark Mllib kmeans 示例,使用数据框而不是文本文件
Spark Mllib kmeans example, with a dataframe instead of textFile
我正在尝试 运行 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()
^
有更好的方法吗?
我读过这篇类似的文章 post,但我觉得它不够相似:
How to turn a known structured RDD to Vector
还有这个
处理文本数据
由于 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)
}
如果您更喜欢位置方法,您可以使用模式匹配而不是应用返回的值:
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)
)
怎么样:
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()
我正在尝试 运行 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()
^
有更好的方法吗?
我读过这篇类似的文章 post,但我觉得它不够相似:
How to turn a known structured RDD to Vector
还有这个
由于 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)
}
如果您更喜欢位置方法,您可以使用模式匹配而不是应用返回的值:
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)
)
怎么样:
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()