Spark - โหลดไฟล์ CSV เป็น DataFrame หรือไม่


142

ฉันต้องการอ่าน CSV อย่างรวดเร็วและแปลงเป็น DataFrame และเก็บไว้ใน HDFS ด้วย df.registerTempTable("table_name")

ฉันเหนื่อย:

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

ข้อผิดพลาดที่ฉันได้รับ:

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)

คำสั่งที่เหมาะสมในการโหลดไฟล์ CSV เป็น DataFrame ใน Apache Spark คืออะไร


ตรวจสอบลิงค์
mrsrinivas

คำตอบ:


181

spark-csv เป็นส่วนหนึ่งของฟังก์ชั่นหลักของ Spark และไม่จำเป็นต้องมีห้องสมุดแยกต่างหาก คุณก็ทำได้เช่นกัน

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

ในสกาลา (ใช้ได้กับตัวคั่นรูปแบบใด ๆ ที่กล่าวถึง "," สำหรับ csv, "\ t" สำหรับ tsv ฯลฯ )

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


164

แยกวิเคราะห์ CSV และโหลดเป็น DataFrame / DataSet ด้วย Spark 2.x

ขั้นแรกให้เริ่มต้นSparkSessionวัตถุโดยค่าเริ่มต้นมันจะมีอยู่ในเปลือกหอยเป็นspark

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

ใช้วิธีใดวิธีหนึ่งต่อไปนี้เพื่อโหลด CSV เป็น DataFrame/DataSet

1. ทำในลักษณะที่เป็นโปรแกรม

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

อัปเดต: เพิ่มตัวเลือกทั้งหมดจากที่นี่ในกรณีที่ลิงก์จะใช้งานไม่ได้ในอนาคต

  • เส้นทาง : ตำแหน่งของไฟล์ คล้ายกับ Spark สามารถยอมรับการแสดงออกที่กลมเป็นมาตรฐาน Hadoop
  • header : เมื่อตั้งค่าเป็นจริงบรรทัดแรกของไฟล์จะถูกใช้เป็นชื่อคอลัมน์และจะไม่รวมอยู่ในข้อมูล ทุกประเภทจะถือว่าเป็นสตริง ค่าเริ่มต้นเป็นเท็จ
  • ตัวคั่น : โดยคอลัมน์เริ่มต้นจะใช้ตัวคั่น แต่ตัวคั่นสามารถตั้งค่าเป็นอักขระใดก็ได้
  • เครื่องหมายอัญประกาศ : โดยค่าเริ่มต้นอักขระเครื่องหมายคำพูดคือ "แต่สามารถตั้งเป็นอักขระใดก็ได้ตัวคั่นภายในเครื่องหมายคำพูดจะถูกละเว้น
  • หลบหนี : โดยค่าเริ่มต้นตัวละครหลบหนีคือ แต่สามารถตั้งค่าให้ตัวละครใด ๆ อักขระคำพูดที่หลีกหนีจะถูกละเว้น
  • parserLib : โดยค่าเริ่มต้นมันคือ " คอมมอนส์ " ที่สามารถตั้งค่าเป็น " univocity " เพื่อใช้ไลบรารีนั้นสำหรับการแยกวิเคราะห์ CSV
  • โหมด : กำหนดโหมดการแยกวิเคราะห์ โดยค่าเริ่มต้นมันเป็นสิทธิ์ ค่าที่เป็นไปได้คือ:
    • สิทธิ์ : พยายามแยกวิเคราะห์บรรทัดทั้งหมด: null ถูกแทรกสำหรับโทเค็นที่ขาดหายไปและโทเค็นพิเศษจะถูกละเว้น
    • DROPMALFORMED : วางสายที่มีโทเค็นน้อยกว่าหรือมากกว่าที่คาดไว้หรือโทเค็นที่ไม่ตรงกับสคีมา
    • FAILFAST : ยกเลิกการทำงานกับ RuntimeException หากพบชุดอักขระบรรทัดที่มีรูปแบบไม่ถูกต้อง: เริ่มต้นที่ 'UTF-8' แต่สามารถตั้งค่าเป็นชื่อชุดอักขระที่ถูกต้องอื่น ๆ
  • inferSchema : infers ประเภทคอลัมน์โดยอัตโนมัติ มันต้องผ่านหนึ่งข้อมูลพิเศษและเป็นเท็จโดยความคิดเห็นเริ่มต้น: ข้ามบรรทัดที่เริ่มต้นด้วยตัวละครนี้ ค่าเริ่มต้นคือ "#" ปิดใช้งานความคิดเห็นด้วยการตั้งค่าเป็น null
  • nullValue : ระบุสตริงที่ระบุค่า null ฟิลด์ใด ๆ ที่ตรงกับสตริงนี้จะถูกตั้งค่าเป็น nulls ใน DataFrame
  • dateFormat : ระบุสตริงที่ระบุรูปแบบวันที่ที่จะใช้เมื่ออ่านวันที่หรือเวลาประทับ รูปแบบวันที่ที่กำหนดเองจะเป็นไปตามรูปแบบที่ java.text.SimpleDateFormat สิ่งนี้ใช้ได้กับทั้ง DateType และ TimestampType โดยค่าเริ่มต้นมันเป็นโมฆะซึ่งหมายถึงการพยายามแยกเวลาและวันที่โดย java.sql.Timestamp.valueOf () และ java.sql.Date.valueOf ()

2. คุณสามารถทำวิธี SQL นี้ได้เช่นกัน

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

การพึ่งพา :

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

รุ่น Spark <2.0

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

อ้างอิง:

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

เซสชันนี้ต้องการกลุ่มไหม ฉันกำลังได้รับข้อผิดพลาดรัง
Puneet

2
ไม่จำเป็น. เท่านั้นspark-core_2.11และspark-sql_2.11ของ2.0.1รุ่นเป็นเรื่องปกติ หากเป็นไปได้ให้เพิ่มข้อความแสดงข้อผิดพลาด
mrsrinivas

1
เราสามารถแปลงไฟล์ที่มีตัวคั่นไปป์เป็นดาต้าเฟรมได้หรือไม่?
Omkar

3
@OmkarPuttagunta: ใช่แน่นอน! ลองบางอย่างเช่นนี้ spark.read.format("csv").option("delimiter ", "|") ...
mrsrinivas

1
ตัวเลือกอื่น ๆ สำหรับprogrammatic wayคือการปล่อยออก.format("csv")และแทนที่ด้วย.load(... วิธีการอยู่ในชั้นเรียน DataFrameReader ที่ส่งกลับโดยวิธีการที่และวิธีการกลับ dataframe จึงไม่สามารถมีตัวเลือกแท็กหลังจากที่พวกเขาเรียกว่า คำตอบนี้ค่อนข้างละเอียด แต่คุณควรเชื่อมโยงไปยังเอกสารเพื่อให้ผู้คนสามารถเห็นตัวเลือก CSV อื่น ๆ ทั้งหมดที่มีอยู่spark.apache.org/docs/latest/api/scala/… *): org.apache.spark.sql.DataFrame.csv(...optionreadloadcsv
Davos

17

ใช้สำหรับ Hadoop ซึ่งเป็น 2.6 และ Spark คือ 1.6 และไม่มีแพ็คเกจ "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

ด้วย Spark 2.0 ต่อไปนี้เป็นวิธีที่คุณสามารถอ่าน 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
มีความแตกต่างระหว่างspark.read.csv(path)และspark.read.format("csv").load(path)?
Eric

8

ใน Java 1.8 โค้ดนี้ทำงานได้อย่างสมบูรณ์ในการอ่านไฟล์ 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>

ชวา

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

ในขณะนี้อาจเป็นประโยชน์กับใครบางคน คำถามมีแท็ก Scala
OneCricketeer

5

มีความท้าทายมากมายในการแยกวิเคราะห์ไฟล์ CSV ซึ่งจะเพิ่มขึ้นเรื่อย ๆ หากขนาดไฟล์ใหญ่กว่าหากมีอักขระที่ไม่ใช่ภาษาอังกฤษ / escape / ตัวคั่น / อักขระอื่น ๆ ในค่าคอลัมน์ซึ่งอาจทำให้เกิดข้อผิดพลาดในการแยกวิเคราะห์

เวทมนตร์นั้นอยู่ในตัวเลือกที่ใช้ เคสที่เหมาะกับฉันและหวังว่าควรครอบคลุมเคสส่วนใหญ่อยู่ในโค้ดด้านล่าง:

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

หวังว่าจะช่วย สำหรับการอ้างอิงเพิ่มเติม: การใช้ PySpark 2 เพื่ออ่าน CSV ที่มีซอร์สโค้ด HTML

หมายเหตุ: โค้ดข้างต้นมาจาก Spark 2 API ซึ่ง API การอ่านไฟล์ CSV มาพร้อมกับแพ็คเกจในตัวของ Spark ที่ติดตั้งได้

หมายเหตุ: PySpark เป็นเครื่องห่อหุ้มงูหลามสำหรับ Spark และแบ่งปัน API เดียวกับ Scala / Java


ขอบคุณมากคุณช่วยชีวิตฉัน: D
Khubaib Raza

4

ตัวอย่าง Penny's Spark 2 เป็นวิธีการทำใน spark2 มีอีกหนึ่งเคล็ดลับ: ให้ส่วนหัวนั้นสร้างขึ้นสำหรับคุณโดยทำการสแกนข้อมูลครั้งแรกโดยตั้งค่าตัวเลือกinferSchemaเป็นtrue

ในที่นี้สมมติว่าsparkเป็นเซสชันแบบประกายไฟที่คุณตั้งไว้คือการดำเนินการเพื่อโหลดในไฟล์ดัชนี CSV ของภาพ Landsat ทั้งหมดที่ amazon โฮสต์บน 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")

ข่าวร้ายคือสิ่งนี้ทำให้เกิดการสแกนไฟล์ สำหรับสิ่งที่มีขนาดใหญ่เช่นไฟล์ CSV ขนาด 20 + MB นี้ซึ่งสามารถใช้เวลา 30 วินาทีในการเชื่อมต่อระยะไกล โปรดจำไว้ว่า: คุณควรเขียนคีมาด้วยตนเองเมื่อคุณเข้ามา

(ข้อมูลโค้ด Apache Software License 2.0 ได้รับใบอนุญาตเพื่อหลีกเลี่ยงความคลุมเครือทั้งหมดสิ่งที่ฉันทำในการทดสอบการรวมกลุ่มของการรวม S3)


ฉันไม่เห็นวิธี csv นี้หรือส่งแผนที่ไปยังตัวเลือกต่างๆ เห็นด้วยเสมอดีกว่าการให้สคีมาอย่างชัดเจน inferSchema นั้นใช้ได้ดีกับสิ่งสกปรกที่รวดเร็ว (วิทยาศาสตร์ข้อมูลหรือที่รู้จัก) แต่แย่มากสำหรับ ETL
Davos

2

ในกรณีที่คุณสร้างขวดที่มี scala 2.11 และ Apache 2.0 หรือสูงกว่า

ไม่จำเป็นต้องสร้าง sqlContextหรือsparkContextวัตถุ เพียงแค่SparkSessionวัตถุพอเพียงความต้องการสำหรับทุกความต้องการ

ต่อไปนี้เป็น mycode ซึ่งทำงานได้ดี:

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

ในกรณีที่คุณกำลังทำงานในกลุ่มเพียงแค่เปลี่ยน .master("local")เป็น.master("yarn")ในขณะที่การกำหนดsparkBuilderวัตถุ

Spark Doc ครอบคลุมสิ่งนี้: https://spark.apache.org/docs/2.2.0/sql-programming-guide.html


นี่เป็นเช่นเดียวกับคำตอบที่มีอยู่
mrsrinivas

0

เพิ่มการพึ่งพา Spark ต่อไปนี้กับไฟล์ 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>

// การกำหนดค่า Spark:

val spark = SparkSession.builder (). master ("local"). appName ("ตัวอย่างแอป"). getOrCreate ()

// อ่านไฟล์ csv:

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

// แสดงผล

df.show ()


0

หากต้องการอ่านจากพา ธ สัมพัทธ์บนระบบใช้เมธอด System.getProperty เพื่อรับไดเร็กทอรีปัจจุบันและใช้เพิ่มเติมเพื่อโหลดไฟล์โดยใช้พา ธ สัมพัทธ์

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)

จุดประกาย: 2.4.4 ขนาด: 2.11.12


0

ด้วย Spark 2.4+ หากคุณต้องการโหลด csv จากไดเรกทอรีท้องถิ่นคุณสามารถใช้ 2 เซสชันและโหลดลงในรัง เซสชันแรกควรสร้างขึ้นด้วยการกำหนดค่า master () เป็น "local [*]" และเซสชันที่สองที่เปิดใช้งาน "yarn" และ Hive

ด้านล่างใช้ได้สำหรับฉัน

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

   }

เมื่อวิ่งไปกับspark2-submit --master "yarn" --conf spark.ui.enabled=false testCSV.jarมันมันก็ดีและสร้างโต๊ะขึ้นมาในรัง


-1

รูปแบบไฟล์เริ่มต้นคือ Parquet ที่มี spark.read .. และอ่านไฟล์ csv ว่าทำไมคุณถึงได้รับข้อยกเว้น ระบุรูปแบบ csv ด้วย api ที่คุณพยายามใช้


-1

ลองใช้ถ้าใช้ 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")

หมายเหตุ: - ใช้งานได้กับไฟล์ที่คั่นทุกตัว เพียงใช้ตัวเลือก (“ ตัวคั่น”,) เพื่อเปลี่ยนค่า

หวังว่านี่จะเป็นประโยชน์


นี่เป็นเช่นเดียวกับคำตอบที่มีอยู่
mrsrinivas

-1

ด้วย Spark csv ในตัวคุณสามารถทำมันได้อย่างง่ายดายด้วยวัตถุ SparkSession ใหม่สำหรับ 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()

มีตัวเลือกต่าง ๆ ที่คุณสามารถตั้งค่าได้

  • header: ระบุว่าไฟล์ของคุณมีบรรทัดส่วนหัวที่ด้านบนหรือไม่
  • inferSchema: ไม่ว่าคุณต้องการอนุมานสคีมาโดยอัตโนมัติหรือไม่ trueเริ่มต้นคือ ฉันชอบที่จะให้สคีมาเพื่อให้แน่ใจว่าประเภทข้อมูลที่เหมาะสม
  • mode: โหมดการวิเคราะห์คำ, PERMISSIVE, DROPMALFORMED หรือ FAILFAST
  • delimiter: เพื่อระบุตัวคั่นค่าเริ่มต้นคือเครื่องหมายจุลภาค (',')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.