J'ai unRDDavec un tuple de valeurs (String, SparseVector) et je veux créer un DataFrame en utilisant leRDD. Pour obtenir un (libellé: chaîne, caractéristiques: vecteur) DataFrame qui est le schéma requis par la plupart des bibliothèques de l'algorithme ml. Je sais que cela peut être fait parce que HashingTF ml Library génère un vecteur lorsque la colonne features d’un DataFrame .
temp_df = sqlContext.createDataFrame(temp_rdd, StructType([
StructField("label", DoubleType(), False),
StructField("tokens", ArrayType(StringType()), False)
]))
#assumming there is an RDD (double,array(strings))
hashingTF = HashingTF(numFeatures=COMBINATIONS, inputCol="tokens", outputCol="features")
ndf = hashingTF.transform(temp_df)
ndf.printSchema()
#outputs
#root
#|-- label: double (nullable = false)
#|-- tokens: array (nullable = false)
#| |-- element: string (containsNull = true)
#|-- features: vector (nullable = true)
Ma question est donc la suivante: puis-je, en quelque sorte, faire en sorte que leRDDde (String, SparseVector) soit converti en un DataFrame de (String, vector). J'ai essayé avec le sqlContext.createDataFrame
habituel mais il n'y a pas de DataType qui correspond à mes besoins.
df = sqlContext.createDataFrame(rdd,StructType([
StructField("label" , StringType(),True),
StructField("features" , ?Type(),True)
]))
Vous devez utiliser VectorUDT
ici:
# In Spark 1.x
# from pyspark.mllib.linalg import SparseVector, VectorUDT
from pyspark.ml.linalg import SparseVector, VectorUDT
temp_rdd = sc.parallelize([
(0.0, SparseVector(4, {1: 1.0, 3: 5.5})),
(1.0, SparseVector(4, {0: -1.0, 2: 0.5}))])
schema = StructType([
StructField("label", DoubleType(), True),
StructField("features", VectorUDT(), True)
])
temp_rdd.toDF(schema).printSchema()
## root
## |-- label: double (nullable = true)
## |-- features: vector (nullable = true)
Juste pour être complet, équivalent Scala:
import org.Apache.spark.sql.Row
import org.Apache.spark.rdd.RDD
import org.Apache.spark.sql.types.{DoubleType, StructType}
// In Spark 1x.
// import org.Apache.spark.mllib.linalg.{Vectors, VectorUDT}
import org.Apache.spark.ml.linalg.Vectors
import org.Apache.spark.ml.linalg.SQLDataTypes.VectorType
val schema = new StructType()
.add("label", DoubleType)
// In Spark 1.x
//.add("features", new VectorUDT())
.add("features",VectorType)
val temp_rdd: RDD[Row] = sc.parallelize(Seq(
Row(0.0, Vectors.sparse(4, Seq((1, 1.0), (3, 5.5)))),
Row(1.0, Vectors.sparse(4, Seq((0, -1.0), (2, 0.5))))
))
spark.createDataFrame(temp_rdd, schema).printSchema
// root
// |-- label: double (nullable = true)
// |-- features: vector (nullable = true)
Alors que @ zero323 répond https://stackoverflow.com/a/32745924/1333621 a un sens, et que cela fonctionne pour moi - le rdd sous-jacent à la trame de données, sqlContext.createDataFrame (temp_rdd, schéma), toujours contenu Types de SparseVectors que j'ai dû effectuer les opérations suivantes pour convertir en types DenseVector - si quelqu'un souhaite utiliser une méthode plus courte/meilleure
temp_rdd = sc.parallelize([
(0.0, SparseVector(4, {1: 1.0, 3: 5.5})),
(1.0, SparseVector(4, {0: -1.0, 2: 0.5}))])
schema = StructType([
StructField("label", DoubleType(), True),
StructField("features", VectorUDT(), True)
])
temp_rdd.toDF(schema).printSchema()
df_w_ftr = temp_rdd.toDF(schema)
print 'original convertion method: ',df_w_ftr.take(5)
print('\n')
temp_rdd_dense = temp_rdd.map(lambda x: Row(label=x[0],features=DenseVector(x[1].toArray())))
print type(temp_rdd_dense), type(temp_rdd)
print 'using map and toArray:', temp_rdd_dense.take(5)
temp_rdd_dense.toDF().show()
root
|-- label: double (nullable = true)
|-- features: vector (nullable = true)
original convertion method: [Row(label=0.0, features=SparseVector(4, {1: 1.0, 3: 5.5})), Row(label=1.0, features=SparseVector(4, {0: -1.0, 2: 0.5}))]
<class 'pyspark.rdd.PipelinedRDD'> <class 'pyspark.rdd.RDD'>
using map and toArray: [Row(features=DenseVector([0.0, 1.0, 0.0, 5.5]), label=0.0), Row(features=DenseVector([-1.0, 0.0, 0.5, 0.0]), label=1.0)]
+------------------+-----+
| features|label|
+------------------+-----+
| [0.0,1.0,0.0,5.5]| 0.0|
|[-1.0,0.0,0.5,0.0]| 1.0|
+------------------+-----+
ceci est un exemple dans scala pour spark 2.1
import org.Apache.spark.ml.linalg.Vector
def featuresRDD2DataFrame(features: RDD[Vector]): DataFrame = {
import sparkSession.implicits._
val rdd: RDD[(Double, Vector)] = features.map(x => (0.0, x))
val df = rdd.toDF("label","features").select("features")
df
}
la toDF()
n'a pas été reconnue par le compilateur dans le dossier d'entités