Spark: carica il file CSV come DataFrame?


142

Vorrei leggere un CSV in Spark e convertirlo come DataFrame e memorizzarlo in HDFS con df.registerTempTable("table_name")

Ho provato:

scala> val df = sqlContext.load("hdfs:///csv/file/dir/file.csv")

Errore che ho ricevuto:

java.lang.RuntimeException: hdfs:///csv/file/dir/file.csv is not a Parquet file. expected magic number at tail [80, 65, 82, 49] but found [49, 59, 54, 10]
    at parquet.hadoop.ParquetFileReader.readFooter(ParquetFileReader.java:418)
    at org.apache.spark.sql.parquet.ParquetRelation2$MetadataCache$$anonfun$refresh$6.apply(newParquet.scala:277)
    at org.apache.spark.sql.parquet.ParquetRelation2$MetadataCache$$anonfun$refresh$6.apply(newParquet.scala:276)
    at scala.collection.parallel.mutable.ParArray$Map.leaf(ParArray.scala:658)
    at scala.collection.parallel.Task$$anonfun$tryLeaf$1.apply$mcV$sp(Tasks.scala:54)
    at scala.collection.parallel.Task$$anonfun$tryLeaf$1.apply(Tasks.scala:53)
    at scala.collection.parallel.Task$$anonfun$tryLeaf$1.apply(Tasks.scala:53)
    at scala.collection.parallel.Task$class.tryLeaf(Tasks.scala:56)
    at scala.collection.parallel.mutable.ParArray$Map.tryLeaf(ParArray.scala:650)
    at scala.collection.parallel.AdaptiveWorkStealingTasks$WrappedTask$class.compute(Tasks.scala:165)
    at scala.collection.parallel.AdaptiveWorkStealingForkJoinTasks$WrappedTask.compute(Tasks.scala:514)
    at scala.concurrent.forkjoin.RecursiveAction.exec(RecursiveAction.java:160)
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

Qual è il comando giusto per caricare il file CSV come DataFrame in Apache Spark?


Risposte:


181

spark-csv fa parte della funzionalità Spark di base e non richiede una libreria separata. Quindi potresti fare solo per esempio

df = spark.read.format("csv").option("header", "true").load("csvfile.csv")

In scala, (funziona con qualsiasi delimitatore di formattazione menzionato "," per csv, "\ t" per tsv ecc.)

val df = sqlContext.read.format("com.databricks.spark.csv") .option("delimiter", ",") .load("csvfile.csv")


164

Analizzare CSV e caricare come DataFrame / DataSet con Spark 2.x

Innanzitutto, inizializza l' SparkSessionoggetto per impostazione predefinita, sarà disponibile nelle shell comespark

val spark = org.apache.spark.sql.SparkSession.builder
        .master("local") # Change it as per your cluster
        .appName("Spark CSV Reader")
        .getOrCreate;

Utilizzare uno dei seguenti modi per caricare CSV come DataFrame/DataSet

1. Fallo in modo programmatico

 val df = spark.read
         .format("csv")
         .option("header", "true") //first line in file has headers
         .option("mode", "DROPMALFORMED")
         .load("hdfs:///csv/file/dir/file.csv")

Aggiornamento: aggiungendo tutte le opzioni da qui nel caso in cui il collegamento venga interrotto in futuro

  • sentiero : posizione dei file. Simile a Spark può accettare le espressioni standard di globbing di Hadoop.
  • header : se impostato su true, la prima riga di file verrà utilizzata per denominare le colonne e non verrà inclusa nei dati. Verranno assunti tutti i tipi di stringa. Il valore predefinito è falso.
  • delimitatore : per impostazione predefinita le colonne vengono delimitate utilizzando, ma il delimitatore può essere impostato su qualsiasi carattere
  • quote : per impostazione predefinita il carattere virgolette è ", ma può essere impostato su qualsiasi carattere. I delimitatori all'interno delle virgolette vengono ignorati
  • escape : per impostazione predefinita, il carattere escape è, ma può essere impostato su qualsiasi carattere. I caratteri di citazione con escape vengono ignorati
  • parserLib : per impostazione predefinita, è " commons " che può essere impostato su " univocità " per utilizzare quella libreria per l'analisi CSV.
  • mode : determina la modalità di analisi. Di default è PERMISSIVO. I valori possibili sono:
    • PERMISSIVE : tenta di analizzare tutte le righe: vengono inseriti null per i token mancanti e i token extra vengono ignorati.
    • DROPMALFORMED : elimina le righe che hanno meno o più token del previsto o token che non corrispondono allo schema
    • FAILFAST : si interrompe con un RuntimeException se rileva un set di caratteri non valido: il valore predefinito è 'UTF-8' ma può essere impostato su altri nomi di set di caratteri validi
  • inferSchema : genera automaticamente i tipi di colonna. Richiede un passaggio aggiuntivo sui dati ed è falso per commento predefinito: salta le righe che iniziano con questo carattere. L'impostazione predefinita è "#". Disabilita i commenti impostando questo su null.
  • nullValue : specifica una stringa che indica un valore null, tutti i campi corrispondenti a questa stringa verranno impostati come null nel DataFrame
  • dateFormat : specifica una stringa che indica il formato della data da utilizzare durante la lettura di date o timestamp. I formati di data personalizzati seguono i formati su java.text.SimpleDateFormat. Questo vale sia per DateType che per TimestampType. Per impostazione predefinita, è null, il che significa che tenta di analizzare l'ora e la data con java.sql.Timestamp.valueOf () e java.sql.Date.valueOf ().

2. Puoi fare anche questo in modo SQL

 val df = spark.sql("SELECT * FROM csv.`hdfs:///csv/file/dir/file.csv`")

Dipendenze :

 "org.apache.spark" % "spark-core_2.11" % 2.0.0,
 "org.apache.spark" % "spark-sql_2.11" % 2.0.0,

Versione Spark <2.0

val df = sqlContext.read
    .format("com.databricks.spark.csv")
    .option("header", "true") 
    .option("mode", "DROPMALFORMED")
    .load("csv/file/path"); 

dipendenze:

"org.apache.spark" % "spark-sql_2.10" % 1.6.0,
"com.databricks" % "spark-csv_2.10" % 1.6.0,
"com.univocity" % "univocity-parsers" % LATEST,

questa sessione richiede l'alveare? Ricevo errori dell'alveare.
Puneet,

2
Non c'è bisogno. Solo spark-core_2.11e spark-sql_2.11della 2.0.1versione va bene. Se possibile aggiungere il messaggio di errore.
mrsrinivas,

1
possiamo convertire un file delimitato da pipe in un dataframe?
Omkar,

3
@OmkarPuttagunta: Sì, certo! prova qualcosa del genere spark.read.format("csv").option("delimiter ", "|") ...
mrsrinivas,

1
L'altra opzione per programmatic wayè quella di lasciare .format("csv")e sostituire .load(...con .csv(.... Il optionmetodo appartiene alla classe DataFrameReader come restituito dal readmetodo, in cui i metodi loade csvrestituiscono un frame di dati, quindi non è possibile contrassegnare le opzioni dopo che sono state chiamate. Questa risposta è piuttosto approfondita, ma dovresti collegarti alla documentazione in modo che le persone possano vedere tutte le altre opzioni CSV disponibili spark.apache.org/docs/latest/api/scala/… *): org.apache.spark.sql.DataFrame
Davos,

17

È per cui Hadoop è 2.6 e Spark è 1.6 e senza pacchetto "databricks".

import org.apache.spark.sql.types.{StructType,StructField,StringType,IntegerType};
import org.apache.spark.sql.Row;

val csv = sc.textFile("/path/to/file.csv")
val rows = csv.map(line => line.split(",").map(_.trim))
val header = rows.first
val data = rows.filter(_(0) != header(0))
val rdd = data.map(row => Row(row(0),row(1).toInt))

val schema = new StructType()
    .add(StructField("id", StringType, true))
    .add(StructField("val", IntegerType, true))

val df = sqlContext.createDataFrame(rdd, schema)

12

Con Spark 2.0, ecco come leggere CSV

val conf = new SparkConf().setMaster("local[2]").setAppName("my app")
val sc = new SparkContext(conf)
val sparkSession = SparkSession.builder
  .config(conf = conf)
  .appName("spark session example")
  .getOrCreate()

val path = "/Users/xxx/Downloads/usermsg.csv"
val base_df = sparkSession.read.option("header","true").
  csv(path)

5
C'è una differenza tra spark.read.csv(path)e spark.read.format("csv").load(path)?
Eric

8

In Java 1.8 Questo frammento di codice funziona perfettamente per leggere i file CSV

pom.xml

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-core_2.11</artifactId>
    <version>2.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-sql_2.10 -->
<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-sql_2.10</artifactId>
    <version>2.0.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.scala-lang/scala-library -->
<dependency>
    <groupId>org.scala-lang</groupId>
    <artifactId>scala-library</artifactId>
    <version>2.11.8</version>
</dependency>
<dependency>
    <groupId>com.databricks</groupId>
    <artifactId>spark-csv_2.10</artifactId>
    <version>1.4.0</version>
</dependency>

Giava

SparkConf conf = new SparkConf().setAppName("JavaWordCount").setMaster("local");
// create Spark Context
SparkContext context = new SparkContext(conf);
// create spark Session
SparkSession sparkSession = new SparkSession(context);

Dataset<Row> df = sparkSession.read().format("com.databricks.spark.csv").option("header", true).option("inferSchema", true).load("hdfs://localhost:9000/usr/local/hadoop_data/loan_100.csv");

        //("hdfs://localhost:9000/usr/local/hadoop_data/loan_100.csv");
System.out.println("========== Print Schema ============");
df.printSchema();
System.out.println("========== Print Data ==============");
df.show();
System.out.println("========== Print title ==============");
df.select("title").show();

Mentre questo può essere utile a qualcuno. La domanda ha un tag Scala.
OneCricketeer,

5

Esistono molte sfide per l'analisi di un file CSV, che continua ad aggiungersi se la dimensione del file è maggiore, se ci sono caratteri non inglesi / escape / separator / altri nei valori della colonna, che potrebbero causare errori di analisi.

La magia quindi è nelle opzioni che vengono utilizzate. Quelli che hanno funzionato per me e la speranza dovrebbero coprire la maggior parte dei casi limite sono nel codice seguente:

### Create a Spark Session
spark = SparkSession.builder.master("local").appName("Classify Urls").getOrCreate()

### Note the options that are used. You may have to tweak these in case of error
html_df = spark.read.csv(html_csv_file_path, 
                         header=True, 
                         multiLine=True, 
                         ignoreLeadingWhiteSpace=True, 
                         ignoreTrailingWhiteSpace=True, 
                         encoding="UTF-8",
                         sep=',',
                         quote='"', 
                         escape='"',
                         maxColumns=2,
                         inferSchema=True)

Spero che aiuti. Per ulteriori informazioni, consultare: Utilizzo di PySpark 2 per leggere CSV con codice sorgente HTML

Nota: il codice sopra riportato proviene dall'API Spark 2, in cui l'API di lettura del file CSV viene fornita in bundle con pacchetti integrati di Spark installabili.

Nota: PySpark è un wrapper Python per Spark e condivide la stessa API di Scala / Java.


Grazie mille, mi hai salvato la vita: D
Khubaib Raza il

4

L'esempio di Penny Spark 2 è il modo di farlo in spark2. C'è ancora un altro trucco: far generare quell'intestazione per te facendo una scansione iniziale dei dati, impostando l'opzione inferSchemasutrue

Qui, quindi, supponendo che sparksia stata impostata una sessione spark, è l'operazione da caricare nel file di indice CSV di tutte le immagini Landsat che Amazon ospita su S3.

  /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *    http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */

val csvdata = spark.read.options(Map(
    "header" -> "true",
    "ignoreLeadingWhiteSpace" -> "true",
    "ignoreTrailingWhiteSpace" -> "true",
    "timestampFormat" -> "yyyy-MM-dd HH:mm:ss.SSSZZZ",
    "inferSchema" -> "true",
    "mode" -> "FAILFAST"))
  .csv("s3a://landsat-pds/scene_list.gz")

La cattiva notizia è: questo avvia una scansione del file; per qualcosa di grande come questo file CSV compresso 20 + MB, che può richiedere 30 secondi su una connessione a lungo raggio. Tienilo a mente: è meglio codificare manualmente lo schema una volta che lo hai inserito.

(frammento di codice Apache Software License 2.0 concesso in licenza per evitare ogni ambiguità; qualcosa che ho fatto come test demo / integrazione dell'integrazione S3)


Non avevo visto questo metodo CSV o passando una mappa alle opzioni. D'accordo sempre meglio fornendo uno schema esplicito, inferSchema va bene per quick n dirty (aka data science) ma terribile per ETL.
Davos,

2

Nel caso in cui si stia costruendo un vaso con scala 2.11 e Apache 2.0 o versioni successive.

Non è necessario creare un oggetto sqlContexto sparkContext. Solo un SparkSessionoggetto è sufficiente per tutte le esigenze.

Di seguito è mycode che funziona bene:

import org.apache.spark.sql.{DataFrame, Row, SQLContext, SparkSession}
import org.apache.log4j.{Level, LogManager, Logger}

object driver {

  def main(args: Array[String]) {

    val log = LogManager.getRootLogger

    log.info("**********JAR EXECUTION STARTED**********")

    val spark = SparkSession.builder().master("local").appName("ValidationFrameWork").getOrCreate()
    val df = spark.read.format("csv")
      .option("header", "true")
      .option("delimiter","|")
      .option("inferSchema","true")
      .load("d:/small_projects/spark/test.pos")
    df.show()
  }
}

Nel caso in cui si stia eseguendo un cluster, passare .master("local")a .master("yarn")durante la definizione sparkBuilderdell'oggetto

Spark Doc tratta questo: https://spark.apache.org/docs/2.2.0/sql-programming-guide.html


Questo è lo stesso delle risposte esistenti
mrsrinivas,

0

Aggiungi le seguenti dipendenze Spark al file POM:

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-core_2.11</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-sql_2.11</artifactId>
    <version>2.2.0</version>
</dependency>

// Configurazione Spark:

val spark = SparkSession.builder (). master ("local"). appName ("App di esempio"). getOrCreate ()

// Leggi il file csv:

val df = spark.read.option ("header", "true"). csv ("FILE_PATH")

// Visualizza output

df.show ()


0

Per leggere dal percorso relativo sul sistema, utilizzare il metodo System.getProperty per ottenere la directory corrente e utilizzare ulteriormente per caricare il file utilizzando il percorso relativo.

scala> val path = System.getProperty("user.dir").concat("/../2015-summary.csv")
scala> val csvDf = spark.read.option("inferSchema","true").option("header", "true").csv(path)
scala> csvDf.take(3)

scintilla: 2.4.4 scala: 2.11.12


0

Con Spark 2.4+, se si desidera caricare un CSV da una directory locale, è possibile utilizzare 2 sessioni e caricarlo in hive. La prima sessione deve essere creata con master () config come "local [*]" e la seconda sessione con "thread" e Hive abilitati.

Quello sotto ha funzionato per me.

import org.apache.log4j.{Level, Logger}
import org.apache.spark._
import org.apache.spark.rdd._
import org.apache.spark.sql._

object testCSV { 

  def main(args: Array[String]) {
    Logger.getLogger("org").setLevel(Level.ERROR)
    val spark_local = SparkSession.builder().appName("CSV local files reader").master("local[*]").getOrCreate()

    import spark_local.implicits._
    spark_local.sql("SET").show(100,false)
    val local_path="/tmp/data/spend_diversity.csv"  // Local file
    val df_local = spark_local.read.format("csv").option("inferSchema","true").load("file://"+local_path) // "file://" is mandatory
    df_local.show(false)

    val spark = SparkSession.builder().appName("CSV HDFS").config("spark.sql.warehouse.dir", "/apps/hive/warehouse").enableHiveSupport().getOrCreate()

    import spark.implicits._
    spark.sql("SET").show(100,false)
    val df = df_local
    df.createOrReplaceTempView("lcsv")
    spark.sql(" drop table if exists work.local_csv ")
    spark.sql(" create table work.local_csv as select * from lcsv ")

   }

Una volta eseguito, spark2-submit --master "yarn" --conf spark.ui.enabled=false testCSV.jarè andato bene e ha creato la tabella in alveare.


-1

Il formato file predefinito è Parquet con spark.read .. e la lettura dei file CSV è il motivo per cui stai ricevendo l'eccezione. Specificare il formato CSV con API che si sta tentando di utilizzare


-1

Prova questo se usi spark 2.0+

For non-hdfs file:
df = spark.read.csv("file:///csvfile.csv")


For hdfs file:
df = spark.read.csv("hdfs:///csvfile.csv")

For hdfs file (with different delimiter than comma:
df = spark.read.option("delimiter","|")csv("hdfs:///csvfile.csv")

Nota: - funziona con qualsiasi file delimitato. Basta usare l'opzione ("delimitatore",) per modificare il valore.

Spero sia utile.


Questo è lo stesso delle risposte esistenti
mrsrinivas,

-1

Con Spark CSV incorporato, puoi farlo facilmente con il nuovo oggetto SparkSession per Spark> 2.0.

val df = spark.
        read.
        option("inferSchema", "false").
        option("header","true").
        option("mode","DROPMALFORMED").
        option("delimiter", ";").
        schema(dataSchema).
        csv("/csv/file/dir/file.csv")
df.show()
df.printSchema()

Ci sono varie opzioni che puoi impostare.

  • header: se il tuo file include la riga di intestazione in alto
  • inferSchema: se si desidera inferire lo schema automaticamente o no. L'impostazione predefinita è true. Preferisco sempre fornire lo schema per garantire i tipi di dati corretti.
  • mode: modalità di analisi, PERMISSIVE, DROPMALFORMED o FAILFAST
  • delimiter: per specificare il delimitatore, il valore predefinito è virgola (',')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.