web-dev-qa-db-fra.com

Comment créer un DataFrame à partir d'un fichier texte dans Spark

J'ai un fichier texte sur HDFS et je veux le convertir en un cadre de données dans Spark.

J'utilise le contexte Spark pour charger le fichier, puis essayer de générer des colonnes individuelles à partir de ce fichier. 

val myFile = sc.textFile("file.txt")
val myFile1 = myFile.map(x=>x.split(";"))

Après cela, je tente l'opération suivante.

myFile1.toDF()

Je reçois un problème car les éléments de myFile1 RDD sont maintenant du type tableau.

Comment puis-je résoudre ce problème?

10
Rahul

Update - à partir de Spark 1.6, vous pouvez simplement utiliser la source de données CSV intégrée:

spark: SparkSession = // create the Spark Session
val df = spark.read.csv("file.txt")

Vous pouvez également utiliser diverses options pour contrôler l'analyse CSV, par exemple:

val df = spark.read.option("header", "false").csv("file.txt")

Pour la version <1.6: .__ de Spark, le moyen le plus simple consiste à utiliser spark-csv - l’inclure dans vos dépendances et à suivre le fichier README, ce qui permet de définir un délimiteur personnalisé (;), capable de lire du CSV en-têtes (si vous en avez), et il peut en déduire le schéma types (avec le coût d'une analyse supplémentaire des données). 

Si vous connaissez le schéma, vous pouvez également créer une classe de cas qui le représente et mapper vos éléments RDD dans des instances de cette classe avant de les transformer en un DataFrame, par exemple:

case class Record(id: Int, name: String)

val myFile1 = myFile.map(x=>x.split(";")).map {
  case Array(id, name) => Record(id.toInt, name)
} 

myFile1.toDF() // DataFrame will have columns "id" and "name"
14
Tzach Zohar

J'ai donné différentes façons de créer DataFrame à partir d'un fichier texte

val conf = new SparkConf().setAppName(appName).setMaster("local")
val sc = SparkContext(conf)

fichier texte brut

val file = sc.textFile("C:\\vikas\\spark\\Interview\\text.txt")
val fileToDf = file.map(_.split(",")).map{case Array(a,b,c) => 
(a,b.toInt,c)}.toDF("name","age","city")
fileToDf.foreach(println(_))

session d'allumage sans schéma

import org.Apache.spark.sql.SparkSession
val sparkSess = 
SparkSession.builder().appName("SparkSessionZipsExample")
.config(conf).getOrCreate()

val df = sparkSess.read.option("header", 
"false").csv("C:\\vikas\\spark\\Interview\\text.txt")
df.show()

session d'allumage avec schéma

import org.Apache.spark.sql.types._
val schemaString = "name age city"
val fields = schemaString.split(" ").map(fieldName => StructField(fieldName, 
StringType, nullable=true))
val schema = StructType(fields)

val dfWithSchema = sparkSess.read.option("header", 
"false").schema(schema).csv("C:\\vikas\\spark\\Interview\\text.txt")
dfWithSchema.show()

en utilisant le contexte SQL

import org.Apache.spark.sql.SQLContext

val fileRdd = 
sc.textFile("C:\\vikas\\spark\\Interview\\text.txt").map(_.split(",")).map{x 
=> org.Apache.spark.sql.Row(x:_*)}
val sqlDf = sqlCtx.createDataFrame(fileRdd,schema)
sqlDf.show()
5
Vikas Singh

Si vous souhaitez utiliser la méthode toDF, vous devez convertir votre RDD de Array[String] en RDD d'une classe de cas. Par exemple, vous devez faire:

case class Test(id:String,filed2:String)
val myFile = sc.textFile("file.txt")
val df= myFile.map( x => x.split(";") ).map( x=> Test(x(0),x(1)) ).toDF()
4
mgaido
val df = spark.read.textFile("abc.txt")

case class Abc (amount:Int, types: String, id:Int)  //columns and data types

val df2 = df.map(rec=>Amount(rec(0).toInt, rec(1), rec(2).toInt))
rdd2.printSchema

root
 |-- amount: integer (nullable = true)
 |-- types: string (nullable = true)
 |-- id: integer (nullable = true)
1
Vishal

Vous ne pourrez pas le convertir en trame de données avant d’utiliser la conversion implicite.

val sqlContext = new SqlContext(new SparkContext())

import sqlContext.implicits._

Après cela, vous pourrez le convertir en trame de données.

case class Test(id:String,filed2:String)

val myFile = sc.textFile("file.txt")

val df= myFile.map( x => x.split(";") ).map( x=> Test(x(0),x(1)) ).toDF()
1
Abhijit

Je sais que je suis assez en retard pour répondre à cette question mais j’ai trouvé une réponse différente:

val rdd = sc.textFile("/home/training/mydata/file.txt")

val text = rdd.map(lines=lines.split(",")).map(arrays=>(ararys(0),arrays(1))).toDF("id","name").show 
0
Ankita

Vous pouvez lire un fichier pour avoir un RDD, puis lui affecter un schéma. Deux manières courantes de créer un schéma sont d'utiliser une classe de cas ou un objet Schema [mon préféré]. Suit les extraits rapides de code que vous pouvez utiliser.

Approche par classe de cas

case class Test(id:String,name:String)
val myFile = sc.textFile("file.txt")
val df= myFile.map( x => x.split(";") ).map( x=> Test(x(0),x(1)) ).toDF()

Approche de schéma

import org.Apache.spark.sql.types._
val schemaString = "id name"
val fields = schemaString.split(" ").map(fieldName => StructField(fieldName, StringType, nullable=true))
val schema = StructType(fields)

val dfWithSchema = sparkSess.read.option("header","false").schema(schema).csv("file.txt")
dfWithSchema.show()

La seconde est mon approche préférée car la classe de cas a une limite de 22 champs maximum, ce qui posera problème si votre fichier contient plus de 22 champs!

0
user9406937