簡體   English   中英

Spark - 將 CSV 文件加載為 DataFrame?

[英]Spark - load CSV file as DataFrame?

我想在 spark 中讀取 CSV 並將其轉換為 DataFrame 並使用df.registerTempTable("table_name")將其存儲在 HDFS 中

我試過了:

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)

在 Apache Spark 中將 CSV 文件加載為 DataFrame 的正確命令是什么?

spark-csv 是核心 Spark 功能的一部分,不需要單獨的庫。 所以你可以做例如

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

在 Scala 中,(這適用於任何格式的分隔符提及“,”對於 csv,“\\t”對於 tsv 等)

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

使用 Spark 2.x 解析 CSV 並加載為 DataFrame/DataSet

首先,默認初始化SparkSession對象,它將在 shell 中作為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 globbing 表達式。
  • header : 當設置為 true 時,文件的第一行將用於命名列並且不會包含在數據中。 所有類型都將假定為字符串。 默認值為假。
  • delimiter : 默認情況下使用分隔列,但分隔符可以設置為任何字符
  • quote : 默認情況下,引號字符是 ",但可以設置為任何字符。引號內的分隔符將被忽略
  • 轉義:默認情況下,轉義字符是 ,但可以設置為任何字符。 忽略轉義的引號字符
  • parserLib :默認情況下,可以將“ commons ”設置為“ univocity ”以使用該庫進行CSV解析。
  • mode :確定解析模式。 默認情況下它是允許的。 可能的值為:
    • PERMISSIVE :嘗試解析所有行:為丟失的標記插入空值,並忽略額外的標記。
    • DROPMALFORMED :刪除令牌比預期少或多的行或與模式不匹配的令牌
    • FAILFAST :如果遇到任何格式錯誤的行字符集,則以 RuntimeException 中止:默認為“UTF-8”,但可以設置為其他有效的字符集名稱
  • inferSchema :自動推斷列類型。 它需要對數據進行一次額外的傳遞,並且默認情況下為 false 注釋:跳過以此字符開頭的行。 默認值為“#”。 通過將其設置為 null 來禁用評論。
  • nullValue : 指定一個表示空值的字符串,任何匹配該字符串的字段都將在 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,

它的 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)

使用 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)

在 Java 1.8 中,此代碼片段非常適合讀取 CSV 文件

POM文件

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

解析 CSV 文件有很多挑戰,如果文件大小更大,它就會不斷增加,如果列值中有非英文/轉義符/分隔符/其他字符,則可能導致解析錯誤。

神奇之處在於所使用的選項。 對我有用並希望涵蓋大多數邊緣情況的代碼如下:

### 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 讀取具有 HTML 源代碼的 CSV

注意:上面的代碼來自 Spark 2 API,其中 CSV 文件讀取 API 與 Spark 可安裝的內置包捆綁在一起。

注意:PySpark 是 Spark 的 Python 包裝器,與 Scala/Java 共享相同的 API。

Penny 的 Spark 2 示例是在 spark2 中實現的方法。 還有一個技巧:通過對數據進行初始掃描,通過將選項inferSchema設置為true ,為您生成該標頭

在這里,假設spark是您已設置的 spark 會話,則是將亞馬遜托管在 S3 上的所有 Landsat 圖像的 CSV 索引文件加載到 CSV 索引文件中的操作。

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

壞消息是:這會觸發對文件的掃描; 對於像這個 20+MB 的壓縮 CSV 文件這樣的大文件,長途連接可能需要 30 秒。 記住這一點:一旦你得到它,你最好手動編碼模式。

(代碼片段 Apache 軟件許可證 2.0 已獲得許可以避免所有歧義;我作為 S3 集成的演示/集成測試所做的一些事情)

如果您正在使用 scala 2.11 和 Apache 2.0 或更高版本構建 jar。

無需創建sqlContextsparkContext對象。 只需一個SparkSession對象就足以滿足所有需求。

以下是我的代碼,它工作正常:

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

如果您在集群中運行,只需在定義sparkBuilder對象時將sparkBuilder .master("local")更改為sparkBuilder .master("yarn")

Spark 文檔涵蓋了這一點: https : //spark.apache.org/docs/2.2.0/sql-programming-guide.html

將以下 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>

火花配置:

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

讀取csv文件:

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

顯示輸出:

df.show()

使用 Spark 2.4+,如果要從本地目錄加載 csv,則可以使用 2 個會話並將其加載到 hive 中。 第一個會話應使用 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它運行良好並在 hive 中創建了表。

要從系統上的相對路徑讀取,請使用 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

默認文件格式是帶有 spark.read.. 和文件讀取 csv 的 Parquet,這就是為什么會出現異常。 使用您嘗試使用的 api 指定 csv 格式

加載CSV文件並將結果作為DataFrame返回。

df=sparksession.read.option("header", true).csv("file_name.csv")

Dataframe將文件視為csv格式。

如果使用 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")

注意:- 這適用於任何分隔文件。 只需使用 option(“delimiter”,) 來更改值。

希望這是有幫助的。

使用內置的 Spark csv,您可以使用 Spark > 2.0 的新 SparkSession 對象輕松完成。

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 : 指定分隔符,默認為逗號(',')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM