Spark-将CSV文件加载为DataFrame吗?


140

我想在Spark中读取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)

在Apache Spark中将CSV文件作为DataFrame加载的正确命令是什么?


Answers:


179

spark-csv是Spark核心功能的一部分,不需要单独的库。所以你可以例如

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

在scala中,(这适用于任何格式分隔符,对于csv而言请提及“,”,对于tsv等则使用“ \ t”等)

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


163

解析CSV并使用Spark 2.x加载为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")

更新:从此处添加所有选项,以防将来链接断开

  • path:文件位置。与Spark类似,可以接受标准的Hadoop全局表达式。
  • header:设置为true时,文件的第一行将用于命名列,并且不会包含在数据中。所有类型均假定为字符串。默认值为false。
  • delimiter:默认情况下,使用来分隔列,但是可以将delimiter设置为任何字符
  • quote:默认情况下,引号字符为“,但可以设置为任何字符。引号内的定界符将被忽略
  • escape:默认情况下,转义字符为,但可以设置为任何字符。转义的引号字符将被忽略
  • parserLib:默认情况下,可以将“ commons ”设置为“ univocity ”,以将该库用于CSV解析。
  • mode:确定解析模式。默认情况下,它是PERMISSIVE。可能的值为:
    • PERMISSIVE:尝试解析所有行:为缺少的令牌插入空值,并忽略多余的令牌。
    • DROPMALFORMED:删除令牌少于或多于预期的行或令牌与模式不匹配
    • FAILFAST:如果遇到任何格式错误的行字符集,则通过RuntimeException中止:默认为'UTF-8',但可以设置为其他有效的字符集名称
  • inferSchema:自动推断列类型。它需要对数据进行一次额外的传递,默认情况下为false:跳过以该字符开头的行。默认值为“#”。将此设置为null以禁用评论。
  • nullValue:指定一个指示空值的字符串,与该字符串匹配的任何字段都将在DataFrame中设置为null
  • dateFormat:指定一个字符串,该字符串指示在读取日期或时间戳时要使用的日期格式。自定义日期格式遵循java.text.SimpleDateFormat的格式。这适用于DateType和TimestampType。默认情况下为null,这意味着尝试通过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,

这个环节需要蜂巢吗?我收到蜂巢错误。
浦那

2
没必要。只有spark-core_2.11spark-sql_2.112.0.1版本是罚款。如果可能,添加错误消息。
mrsrinivas

1
我们可以将管道定界文件转换为数据帧吗?
Omkar's

3
@OmkarPuttagunta:是的,当然!尝试这样的事情 spark.read.format("csv").option("delimiter ", "|") ...
mrsrinivas

1
的另一个选择programmatic way是不使用.format("csv")并替换.load(....csv(...。该option方法属于该方法返回的DataFrameReader类read,其中loadcsv方法返回一个数据框,因此调用它们后不能在选项上加上标记。这个答案是非常彻底的,但你应该链接到文档,以便人们可以看到所有可用的其他选项CSV spark.apache.org/docs/latest/api/scala/... *):org.apache.spark.sql.DataFrame
达沃斯

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文件面临很多挑战,如果文件大小较大,列值中包含非英语/转义符/分隔符/其他字符,则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。


非常感谢,您救了我的命:D
拜卜·拉扎

4

Penny的Spark 2示例是在spark2中执行此操作的方法。还有另外一个技巧:通过对数据进行初始扫描,将选项设置为inferSchema来为您生成该标头true

然后,在这里,假设spark您已设置了Spark 会话,该操作将在Amazon托管在S3上的所有Landsat图像的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 Software License 2.0的许可,避免了所有歧义;我已经做过S3集成的演示/集成测试)


我没有看到此csv方法或未将地图传递给选项。同意提供显式架构总是更好,inferSchema适用于快速更新(又称数据科学),但对于ETL则很糟糕。
达沃斯'18

2

如果您要使用Scala 2.11和Apache 2.0或更高版本来构建jar。

无需创建sqlContextsparkContext对象。只需一个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>

//火花配置:

val spark = SparkSession.builder()。master(“ local”)。appName(“ Sample App”)。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个会话并将其加载到hive中。第一个会话应使用master()config创建为“ 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 with spark.read ..和文件读取csv,这就是为什么您遇到异常的原因。使用您要使用的api指定csv格式


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

注意:-此功能适用于任何定界文件。只需使用option(“ delimiter”,)即可更改值。

希望这会有所帮助。


这与现有答案相同
mrsrinivas

-1

借助内置的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:指定分隔符,默认为逗号(',')
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.