将数据帧转换为 libsvm 格式
Posted
技术标签:
【中文标题】将数据帧转换为 libsvm 格式【英文标题】:convert dataframe to libsvm format 【发布时间】:2017-10-10 17:36:14 【问题描述】:我有一个由 sql 查询产生的数据框
df1 = sqlContext.sql("select * from table_test")
我需要将此数据帧转换为 libsvm 格式,以便可以将其作为输入提供给
pyspark.ml.classification.LogisticRegression
我尝试执行以下操作。但是,这导致了以下错误,因为我使用的是 spark 1.5.2
df1.write.format("libsvm").save("data/foo")
Failed to load class for data source: libsvm
我想改用 MLUtils.loadLibSVMFile。我在防火墙后面,不能直接 pip 安装它。所以我下载了文件,对其进行了 scp 编辑,然后手动安装了它。一切似乎都正常,但我仍然收到以下错误
import org.apache.spark.mllib.util.MLUtils
No module named org.apache.spark.mllib.util.MLUtils
问题 1:我上述的方法是否正确。 问题 2:如果问题 1“是”,如何让 MLUtils 工作。如果“否”,的最佳方法是什么
【问题讨论】:
你能提供一个df1行的例子吗?因为如您所见here 和here,saveAsLibSVMFile 需要一个LabeledPoint 的RDD,所以在将dataframe 转换为libsvm 之前,您必须考虑df1 中数据的含义。 而不是import org.apache.spark.mllib.util.MLUtils
,你试过from pyspark.mllib.util import MLUtils
吗?
from pyspark.mllib.util import MLUtils 做到了。谢谢
【参考方案1】:
我会那样做(这只是一个带有任意数据框的示例,我不知道您的 df1 是如何完成的,重点是数据转换):
这是我将数据帧转换为 libsvm 格式的方法:
# ... your previous imports
from pyspark.mllib.util import MLUtils
from pyspark.mllib.regression import LabeledPoint
# A DATAFRAME
>>> df.show()
+---+---+---+
| _1| _2| _3|
+---+---+---+
| 1| 3| 6|
| 4| 5| 20|
| 7| 8| 8|
+---+---+---+
# FROM DATAFRAME TO RDD
>>> c = df.rdd # this command will convert your dataframe in a RDD
>>> print (c.take(3))
[Row(_1=1, _2=3, _3=6), Row(_1=4, _2=5, _3=20), Row(_1=7, _2=8, _3=8)]
# FROM RDD OF TUPLE TO A RDD OF LABELEDPOINT
>>> d = c.map(lambda line: LabeledPoint(line[0],[line[1:]])) # arbitrary mapping, it's just an example
>>> print (d.take(3))
[LabeledPoint(1.0, [3.0,6.0]), LabeledPoint(4.0, [5.0,20.0]), LabeledPoint(7.0, [8.0,8.0])]
# SAVE AS LIBSVM
>>> MLUtils.saveAsLibSVMFile(d, "/your/Path/nameFolder/")
您将在“/your/Path/nameFolder/part-0000*”文件中看到的是:
1.0 1:3.0 2:6.0
4.0 1:5.0 2:20.0
7.0 1:8.0 2:8.0
请参阅 here 获取 LabeledPoint 文档
【讨论】:
如果DataFrame包含None
怎么办?
我目前还在尝试将 LibSVM 格式作为标准化格式,用于在 Spark 项目中在 Python 和 Java 之间交换标签/特征数据集。但是,我对根据@titiro89 的解决方案创建的多个文件感到有些困惑。为什么将数据拆分到多个文件中,如何将其保存到单个文本文件中?或者,我怎样才能读取这些多个“part-0000*”文件? AFAICS,Spark的MLUtils.util中的方法loadLibSVMFile()
需要单个文件,很奇怪; saveAsLibSVMFile()
在同一个util文件中会产生多个文件。【参考方案2】:
我必须这样做才能让它工作
D.map(lambda line: LabeledPoint(line[0],[line[1],line[2]]))
【讨论】:
到目前为止,这是一条评论。请解释为什么这对您有用以及为什么接受的答案不起作用。请自行回答。【参考方案3】:如果您想将稀疏向量转换为更高效的“稀疏”libsvm,请尝试以下操作:
from pyspark.ml.linalg import Vectors
from pyspark.mllib.linalg import Vectors as MLLibVectors
from pyspark.mllib.regression import LabeledPoint
from pyspark.mllib.util import MLUtils
df = spark.createDataFrame([
(0, Vectors.sparse(5, [(1, 1.0), (3, 7.0)])),
(1, Vectors.sparse(5, [(1, 1.0), (3, 7.0)])),
(1, Vectors.sparse(5, [(1, 1.0), (3, 7.0)]))
], ["label", "features"])
df.show()
# +-----+-------------------+
# |label| features|
# +-----+-------------------+
# | 0|(5,[1,3],[1.0,7.0])|
# | 1|(5,[1,3],[1.0,7.0])|
# | 1|(5,[1,3],[1.0,7.0])|
# +-----+-------------------+
MLUtils.saveAsLibSVMFile(df.rdd.map(lambda x: LabeledPoint(x.label, MLLibVectors.fromML(x.features))), './libsvm')
【讨论】:
以上是关于将数据帧转换为 libsvm 格式的主要内容,如果未能解决你的问题,请参考以下文章
将分类数据转换为数字并保存为 libsvm 格式 python
如何从 libSVM 中使用的数据集转换为 weka 中使用的格式数据(*.arff 或 *.csv)