【问题标题】:How to read multiple Excel files and concatenate them into one Apache Spark DataFrame?如何读取多个 Excel 文件并将它们连接成一个 Apache Spark DataFrame?
【发布时间】:2017-08-02 14:06:38
【问题描述】:

最近我想在 Spark Summit 2016 上做 Spark Machine Learning Lab。培训视频是here,导出的笔记本是可用的here.

实验室使用的数据集可以从UCI Machine Learning Repository下载。它包含一组来自燃气发电厂中各种传感器的读数。格式为五张xlsx文件。

为了在实验室中使用数据,我需要从 Excel 文件中读取所有工作表并将它们连接到一个 Spark DataFrame 中。在培训期间,他们使用的是 Databricks Notebook,但我使用的是带有 Scala 的 IntelliJ IDEA 并在控制台中评估代码。

第一步是将所有 Excel 工作表保存到名为 sheet1.xlxssheet2.xlsx 等的单独 xlsx 文件中,并将它们放入 sheets 目录中。

如何读取所有 Excel 文件并将它们连接到一个 Apache Spark DataFrame 中?

【问题讨论】:

    标签: excel scala apache-spark apache-spark-dataset spark-excel


    【解决方案1】:

    为此,我使用了spark-excel 包。它可以添加到 build.sbt 文件中:libraryDependencies += "com.crealytics" %% "spark-excel" % "0.8.2"

    在 IntelliJ IDEA Scala 控制台中执行的代码是:

    import org.apache.spark.{SparkConf, SparkContext}
    import org.apache.spark.sql.{SparkSession, DataFrame}
    import java.io.File
    
    val conf = new SparkConf().setAppName("Excel to DataFrame").setMaster("local[*]")
    val sc = new SparkContext(conf)
    sc.setLogLevel("WARN")
    
    val spark = SparkSession.builder().getOrCreate()
    
    // Function to read xlsx file using spark-excel. 
    // This code format with "trailing dots" can be sent to IJ Scala Console as a block.
    def readExcel(file: String): DataFrame = spark.read.
      format("com.crealytics.spark.excel").
      option("location", file).
      option("useHeader", "true").
      option("treatEmptyValuesAsNulls", "true").
      option("inferSchema", "true").
      option("addColorColumns", "False").
      load()
    
    val dir = new File("./data/CCPP/sheets")
    val excelFiles = dir.listFiles.sorted.map(f => f.toString)  // Array[String]
    
    val dfs = excelFiles.map(f => readExcel(f))  // Array[DataFrame]
    val ppdf = dfs.reduce(_.union(_))  // DataFrame 
    
    ppdf.count()  // res3: Long = 47840
    ppdf.show(5)
    

    控制台输出:

    +-----+-----+-------+-----+------+
    |   AT|    V|     AP|   RH|    PE|
    +-----+-----+-------+-----+------+
    |14.96|41.76|1024.07|73.17|463.26|
    |25.18|62.96|1020.04|59.08|444.37|
    | 5.11| 39.4|1012.16|92.14|488.56|
    |20.86|57.32|1010.24|76.64|446.48|
    |10.82| 37.5|1009.23|96.62| 473.9|
    +-----+-----+-------+-----+------+
    only showing top 5 rows 
    

    【讨论】:

    • Not dure 如果它处理不是的 excel 的所有选项卡。是吗?
    • 我会试试的,但提前知道会节省时间
    【解决方案2】:

    希望这个 Spark Scala 代码可能会有所帮助。

    import org.apache.hadoop.conf.Configuration
    import org.apache.hadoop.fs.{Path, FileSystem}
    import org.apache.spark.deploy.SparkHadoopUtil
    import org.apache.spark.sql.execution.datasources.InMemoryFileIndex
    import java.net.URI
    
    def listFiles(basep: String, globp: String): Seq[String] = {
      val conf = new Configuration(sc.hadoopConfiguration)
      val fs = FileSystem.get(new URI(basep), conf)
    
      def validated(path: String): Path = {
        if(path startsWith "/") new Path(path)
        else new Path("/" + path)
      }
    
      val fileCatalog = InMemoryFileIndex.bulkListLeafFiles(
        paths = SparkHadoopUtil.get.globPath(fs, Path.mergePaths(validated(basep), validated(globp))),
        hadoopConf = conf,
        filter = null,
        sparkSession = spark)
    
      fileCatalog.flatMap(_._2.map(_.path))
    }
    
    val root = "/mnt/{path to your file directory}"
    val globp = "[^_]*"
    
    val files = listFiles(root, globp)
    val paths=files.toVector
    

    循环向量读取多个文件:

    for (path <- paths) {
         print(path.toString)
    
         val df= spark.read.
                       format("com.crealytics.spark.excel").
                       option("useHeader", "true").
                       option("treatEmptyValuesAsNulls", "false").
                       option("inferSchema", "false"). 
                       option("addColorColumns", "false").
                       load(path.toString)
    }
    

    【讨论】:

      【解决方案3】:

      为此我们需要 spark-excel 库,可以从

      获得

      https://github.com/crealytics/spark-excel#scala-api

      1. 从上面的 github 链接克隆 git 项目并使用“sbt package”构建
      2. 使用 Spark 2 运行 spark-shell

      spark-shell --driver-class-path ./spark-excel_2.11-0.8.3.jar --master=yarn-client

      1. 导入必要的

      导入 org.apache.spark.sql._
      导入 org.apache.spark.sql.functions._
      val sqlContext = new SQLContext(sc)

      1. 设置excel文档路径

      val document = "path to excel doc"

      1. 执行以下函数以从中创建数据框
      val dataDF = sqlContext.read
                                .format("com.crealytics.spark.excel")
                                .option("sheetName", "Sheet Name")
                                .option("useHeader", "true")
                                .option("treatEmptyValuesAsNulls", "false")
                                .option("inferSchema", "false")
                                .option("location", document)
                                .option("addColorColumns", "false")
                                .load(document)
      

      就是这样!现在您可以对 dataDF 对象执行 Dataframe 操作了。

      【讨论】:

        猜你喜欢
        • 2018-12-14
        • 2022-09-23
        • 1970-01-01
        • 2014-01-21
        • 2022-11-26
        • 1970-01-01
        • 1970-01-01
        • 2014-01-21
        相关资源
        最近更新 更多