Spark - CSV-Datei als DataFrame laden?


140

Ich möchte eine CSV in Spark lesen und als DataFrame konvertieren und in HDFS mit speichern df.registerTempTable("table_name")

Ich habe versucht:

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

Fehler, den ich bekommen habe:

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)

Was ist der richtige Befehl, um eine CSV-Datei als DataFrame in Apache Spark zu laden?


Antworten:


179

spark-csv ist Teil der Spark-Kernfunktionalität und erfordert keine separate Bibliothek. Sie könnten es also zum Beispiel tun

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

In scala (dies funktioniert für alle Format-in-Trennzeichen, die "," für csv, "\ t" für tsv usw. erwähnen).

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


163

Analysieren Sie CSV und laden Sie es mit Spark 2.x als DataFrame / DataSet

Initialisieren Sie zunächst das SparkSessionObjekt standardmäßig, das in Shells als verfügbar istspark

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

Verwenden Sie eine der folgenden Möglichkeiten, um CSV als zu laden DataFrame/DataSet

1. Machen Sie es programmatisch

 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")

Update: Hinzufügen aller Optionen von hier aus, falls der Link in Zukunft unterbrochen wird

  • Pfad : Speicherort der Dateien. Ähnlich wie Spark können Standard-Hadoop-Globbing-Ausdrücke akzeptiert werden.
  • Header : Wenn dieser Wert auf true gesetzt ist, wird die erste Zeile der Dateien zum Benennen von Spalten verwendet und nicht in die Daten aufgenommen. Alle Typen werden als Zeichenfolge angenommen. Der Standardwert ist false.
  • Trennzeichen : Standardmäßig werden Spalten mit begrenzt, aber das Trennzeichen kann auf ein beliebiges Zeichen festgelegt werden
  • Zitat : Standardmäßig lautet das Anführungszeichen ", kann jedoch auf ein beliebiges Zeichen gesetzt werden. Trennzeichen in Anführungszeichen werden ignoriert
  • Flucht : Standardmäßig ist das Escape-Zeichen, kann aber auf ein beliebiges Zeichen gesetzt werden. Escape-Anführungszeichen werden ignoriert
  • parserLib : Standardmäßig können " commons " auf " univocity " gesetzt werden " gesetzt werden, um diese Bibliothek für die CSV-Analyse zu verwenden.
  • mode : Bestimmt den Parsing-Modus. Standardmäßig ist es ERLAUBT. Mögliche Werte sind:
    • PERMISSIVE : Versucht , alle Zeilen zu analysieren: Nullen werden für fehlende Token eingefügt und zusätzliche Token werden ignoriert.
    • DROPMALFORMED : Löscht Zeilen mit weniger oder mehr Token als erwartet oder Token, die nicht mit dem Schema übereinstimmen
    • FAILFAST : Bricht mit einer RuntimeException ab, wenn ein fehlerhafter Zeilenzeichensatz auftritt : Der Standardwert ist 'UTF-8', kann jedoch auf andere gültige Zeichensatznamen festgelegt werden
  • inferSchema : automatisch . Es erfordert einen zusätzlichen Durchlauf über die Daten und ist standardmäßig falsch. Überspringen Sie Zeilen, die mit diesem Zeichen beginnen. Standard ist "#". Deaktivieren Sie Kommentare, indem Sie dies auf null setzen.
  • nullValue : Gibt eine Zeichenfolge an, die einen Nullwert angibt. Alle Felder, die mit dieser Zeichenfolge übereinstimmen, werden im DataFrame als Nullen festgelegt
  • dateFormat : Gibt eine Zeichenfolge an, die das Datumsformat angibt, das beim Lesen von Datums- oder Zeitstempeln verwendet werden soll. Benutzerdefinierte Datumsformate folgen den Formaten unter java.text.SimpleDateFormat. Dies gilt sowohl für DateType als auch für TimestampType. Standardmäßig ist es null, was bedeutet, dass versucht wird, Zeiten und Datum mit java.sql.Timestamp.valueOf () und java.sql.Date.valueOf () zu analysieren.

2. Sie können diese SQL-Methode auch ausführen

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

Abhängigkeiten :

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

Spark-Version <2.0

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

Abhängigkeiten:

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

Benötigt diese Sitzung Bienenstock? Ich bekomme Bienenstockfehler.
Puneet

2
Das ist nicht nötig. Nur spark-core_2.11und spark-sql_2.11der 2.0.1Version ist in Ordnung. Wenn möglich, fügen Sie die Fehlermeldung hinzu.
Fraurinivas

1
Können wir eine durch Pipe getrennte Datei in einen Datenrahmen konvertieren?
Omkar

3
@ OmkarPuttagunta: Ja, natürlich! versuchen Sie etwas wie dieses spark.read.format("csv").option("delimiter ", "|") ...
Fraurinivas

1
Die andere Option für programmatic wayausgeschaltet ist, zu gehen .format("csv")und ersetzen .load(...mit .csv(.... Die optionMethode gehört zur DataFrameReader-Klasse, wie sie von der readMethode zurückgegeben wird, wobei die Methoden loadund csveinen Datenrahmen zurückgeben, sodass nach dem Aufruf keine Optionen markiert werden können. Diese Antwort ist ziemlich gründlich, aber Sie sollten einen Link zur Dokumentation erstellen, damit die Benutzer alle anderen verfügbaren CSV-Optionen sehen können. Spark.apache.org/docs/latest/api/scala/… *): org.apache.spark.sql.DataFrame
Davos

17

Es ist für dessen Hadoop 2.6 und Spark 1.6 ist und ohne "Databricks" -Paket.

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

Mit Spark 2.0 können Sie CSV wie folgt lesen

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
Gibt es einen Unterschied zwischen spark.read.csv(path)und spark.read.format("csv").load(path)?
Eric

8

In Java 1.8 Dieses Code-Snippet funktioniert perfekt zum Lesen von CSV-Dateien

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>

Java

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();

Während dies für jemanden nützlich sein kann. Die Frage hat einen Scala-Tag.
OneCricketeer

5

Das Parsen einer CSV-Datei ist mit vielen Herausforderungen verbunden. Wenn die Dateigröße größer ist und die Spaltenwerte nicht Englisch / Escape / Separator / andere Zeichen enthalten, kann dies zu Analysefehlern führen.

Die Magie liegt dann in den Optionen, die verwendet werden. Diejenigen, die für mich gearbeitet haben und hoffen, dass sie die meisten Randfälle abdecken, sind im folgenden Code aufgeführt:

### 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)

Hoffentlich hilft das. Weitere Informationen finden Sie unter : Verwenden von PySpark 2 zum Lesen von CSV mit HTML-Quellcode

Hinweis: Der obige Code stammt aus der Spark 2-API, in der die CSV-API zum Lesen von Dateien mit integrierten Paketen von Spark geliefert wird, die installiert werden können.

Hinweis: PySpark ist ein Python-Wrapper für Spark und verwendet dieselbe API wie Scala / Java.



4

Pennys Spark 2-Beispiel ist der Weg, dies in spark2 zu tun. Es gibt noch einen weiteren Trick: Lassen Sie diesen Header für Sie generieren, indem Sie einen ersten Scan der Daten durchführen und die Option inferSchemaauf setzentrue

Angenommen, es sparkhandelt sich um eine Spark-Sitzung, die Sie eingerichtet haben, ist die Operation, die in die CSV-Indexdatei aller Landsat-Bilder geladen wird, die Amazon auf S3 hostet.

  /*
   * 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")

Die schlechte Nachricht ist: Dies löst einen Scan durch die Datei aus; Für etwas Großes wie diese 20 + MB komprimierte CSV-Datei kann dies über eine Langstreckenverbindung 30 Sekunden dauern. Denken Sie daran: Sie sollten das Schema besser manuell codieren, sobald Sie es erhalten haben.

(Code-Snippet Apache Software License 2.0, lizenziert, um alle Unklarheiten zu vermeiden; etwas, das ich als Demo / Integrationstest der S3-Integration durchgeführt habe)


Ich hatte diese CSV-Methode nicht gesehen oder eine Karte an Optionen übergeben. InferSchema ist immer besser dran, ein explizites Schema bereitzustellen. Es ist in Ordnung für schnelles und schmutziges (auch bekannt als Data Science), aber für ETL schrecklich.
Davos

2

Falls Sie ein Glas mit Scala 2.11 und Apache 2.0 oder höher erstellen.

Es ist nicht erforderlich, ein sqlContextoder ein sparkContextObjekt zu erstellen . Nur ein SparkSessionObjekt genügt für alle Anforderungen.

Folgendes ist Mycode, der gut funktioniert:

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()
  }
}

Wenn Sie im Cluster ausgeführt werden, wechseln Sie einfach .master("local")zu, .master("yarn")während Sie das sparkBuilderObjekt definieren

Das Spark-Dokument behandelt dies: https://spark.apache.org/docs/2.2.0/sql-programming-guide.html


Dies ist das gleiche wie bestehende Antworten
Fraurinivas

0

Fügen Sie der POM-Datei folgende Spark-Abhängigkeiten hinzu:

<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>

// Spark-Konfiguration:

val spark = SparkSession.builder (). master ("local"). appName ("Beispiel-App"). getOrCreate ()

// CSV-Datei lesen:

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

// Ausgabe anzeigen

df.show ()


0

Um aus dem relativen Pfad auf dem System zu lesen, verwenden Sie die System.getProperty-Methode, um das aktuelle Verzeichnis abzurufen, und verwenden Sie außerdem das Laden der Datei unter Verwendung des relativen Pfads.

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)

Funke: 2.4.4 Scala: 2.11.12


0

Wenn Sie mit Spark 2.4+ eine CSV aus einem lokalen Verzeichnis laden möchten, können Sie zwei Sitzungen verwenden und diese in den Hive laden. Die erste Sitzung sollte mit master () config als "local [*]" und die zweite Sitzung mit "yarn" und Hive aktiviert sein.

Das folgende hat für mich funktioniert.

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 ")

   }

Als es lief spark2-submit --master "yarn" --conf spark.ui.enabled=false testCSV.jar, ging es gut und erstellte den Tisch im Bienenstock.


-1

Das Standarddateiformat ist Parkett mit spark.read .. und CSV zum Lesen von Dateien, weshalb Sie die Ausnahme erhalten. Geben Sie das CSV-Format mit der API an, die Sie verwenden möchten


-1

Versuchen Sie dies, wenn Sie Spark 2.0+ verwenden

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")

Hinweis: - Dies funktioniert für alle durch Trennzeichen getrennten Dateien. Verwenden Sie einfach die Option ("Trennzeichen"), um den Wert zu ändern.

Hoffe das ist hilfreich.


Dies ist das gleiche wie bestehende Antworten
Fraurinivas

-1

Mit der integrierten Spark-CSV können Sie dies problemlos mit dem neuen SparkSession-Objekt für Spark> 2.0 erledigen.

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()

Es gibt verschiedene Optionen, die Sie einstellen können.

  • header: ob Ihre Datei oben eine Kopfzeile enthält
  • inferSchema: ob Sie das Schema automatisch ableiten möchten oder nicht. Standard ist true. Ich bevorzuge es immer, ein Schema bereitzustellen, um die richtigen Datentypen sicherzustellen.
  • mode: Parsing-Modus, PERMISSIVE, DROPMALFORMED oder FAILFAST
  • delimiter: Um ein Trennzeichen anzugeben, ist der Standardwert Komma (',').
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.