【问题标题】:how to read excel data into a dataframe in spark/scala如何将excel数据读入spark/scala中的数据框
【发布时间】:2020-08-11 00:47:01
【问题描述】:

我有一个要求,我需要在 spark/scala 中读取 excel 文件(扩展名为 .xlsx)。我需要使用从 excel 读取的数据创建一个数据框,并在其上应用/写入 sql 查询以进行一些分析。 excel 文件有一些列标题/标题,如“time_spend_company (Years)”、“average_monthly_hours (hours)”等,作为标题本身的空格,这些空格会导致我在加载的数据帧上应用任何 sql 查询的问题。

我正在使用 com.crealytics.spark.excel 库来解析 excel 内容,我的代码如下所示

val empFile = "C:\\EmpDatasets.xlsx"

val employeesDF = sc.sqlContext.read
  .format("com.crealytics.spark.excel")
  .option("sheetName", "Sheet1")
  .option("useHeader", "true")
  .option("treatEmptyValuesAsNulls", "false")
  .option("inferSchema", "false")
  .option("location", empFile)
  .option("addColorColumns", "False")
  .load()

employeesDF.createOrReplaceTempView("EMP")

我想在这些列上应用一些 group by 和其他聚合函数,我遇到了这些列的问题,如下所示,我的要求是在 time_spent_company 列上应用 group by 并获得计数它。

val expLevel = sc.sqlContext.sql("Select 'time_spend_company (Years)' as 'Years_spent_in_company',count(1) from EMP where left_company = 1 group by 'time_spend_company (Years)'")
expLevel.show

我需要帮助:-

  1. 有没有更好的方法来加载 Excel 并为其分配自定义列名并创建数据框?
  2. 如何为这些包含空格的列名编写 sql 查询?

注意:我只需要将其读取为 excel 文件,我无法转换为 csv 或任何其他文件格式。

【问题讨论】:

    标签: scala apache-spark dataframe spark-dataframe


    【解决方案1】:

    对于版本0.13.5,您将需要一组不同的参数:

    def readExcel(file: String): DataFrame = {
        sqlContext.read
          .format("com.crealytics.spark.excel")
          .option("dataAddress", "'sheet_name'!A1") // Optional, default: "A1"
          .option("header", "true") // Required
          .option("treatEmptyValuesAsNulls", "false") // Optional, default: true
          .option("inferSchema", "true") // Optional, default: false
          .option("addColorColumns", "false") // Optional, default: false
          .option("timestampFormat", "MM-dd-yyyy HH:mm:ss") // Optional, default: yyyy-mm-dd hh:mm:ss[.fffffffff]
          .option("maxRowsInMemory", 20) // Optional, d[#All]efault None. If set, uses a streaming reader which can help with big files
          .load(file)
      }
    

    maven 依赖:

    <dependency>
      <groupId>com.crealytics</groupId>
      <artifactId>spark-excel_2.11</artifactId>
      <version>0.13.5</version>
    </dependency>
    

    【讨论】:

      【解决方案2】:

      问题 2 的答案:尽管使用 ',但您需要在带有空格的列名称的开头和结尾之前使用 `。试试下面的查询它会工作:

      val expLevel = sc.sqlContext.sql("Select `time_spend_company (Years)` as `Years_spent_in_company`,count(1) from EMP where left_company = 1 group by `time_spend_company (Years)`")
      

      问题 1:使用“com.crealytics.spark.excel”加载 excel 是可以的。我也在使用它。也可以有不同的选择。要分配不同的列名,您可以使用 Struct Type 来定义架构并在将数据加载到数据帧期间强制执行它。例如

      val newSchema = StructType(
          List(StructField("a", IntegerType, nullable = true),
               StructField("b", IntegerType, nullable = true),
               StructField("c", IntegerType, nullable = true),
               StructField("d", IntegerType, nullable = true))
        )
      
      val employeesDF = spark.read.schema(newSchema)
        .format("com.crealytics.spark.excel")
        .option("sheetName", "Sheet1")
        .option("useHeader", "true")
        .option("treatEmptyValuesAsNulls", "false")
        .option("inferSchema", "false")
        .option("location", empFile)
        .option("addColorColumns", "False")
        .load()
      

      现在将由 a、b、c 和 d 访问前四个列名。运行下面的查询,它将适用于新的列名。

      sc.sqlContext.sql("select a,b,c,d from EMP").show()
      

      【讨论】:

      • 我尝试根据您的建议定义架构并加载数据集,但出现如下异常:- 线程“main”org.apache.spark.sql.AnalysisException: com. crealytics.spark.excel 不允许用户指定的模式。在 org.apache.spark.sql.execution.datasources.DataSource.resolveRelation(DataSource.scala:313) 在 org.apache.spark.sql.DataFrameReader.load(DataFrameReader.scala:178) 在 org.apache.spark.sql .DataFrameReader.load(DataFrameReader.scala:146) 在 EmpPerformanceAnalysis$.main(EmpPerformanceAnalysis.scala:58)
      • val empSchema = StructType( List(StructField("satisfaction_level", FloatType, nullable = true), StructField("last_evaluation", FloatType, nullable = true), .. StructField("salary", StringType , nullable = true)) ) val employeesDF = sc.sqlContext.read.schema(empSchema) .format("com.crealytics.spark.excel") .option("sheetName", "Sheet1") .option("useHeader" , "true") .option("treatEmptyValuesAsNulls", "false") .option("inferSchema", "false") .option("location", empFile) .option("addColorColumns", "False") .load( )
      • @Krishnan 我在 spark 2.1.0 和 scala 2.11 上运行相同。我没有得到你提到的例外。对于您发布的代码,我收到异常“java.lang.IllegalArgumentException:选项中缺少参数“路径”。” .然后我添加了路径选项代替位置选项,它工作正常。
      • 这就是我正在运行的:val employeesDF2 = spark.sqlContext.read.schema(empSchema).format("com.crealytics.spark.excel").option("sheetName", "Sheet1 ").option("useHeader", "true").option("treatEmptyValuesAsNulls", "false").option("inferSchema", "false").option("location", "csvdatatest/Book1.xlsx") .option("addColorColumns", "False").load("csvdatatest/Book1.xlsx")
      • printschema 结果是 : scala> employeesDF2.printSchema root |-- 满意级别:float (nullable = true) |-- last_evaluation: float (nullable = true) |-- 工资:string (nullable = true )
      【解决方案3】:
      1. Spark 对使用 CSV 有很好的支持。因此,如果您的 excel 文件只有一张表,您只需将 EmpDatasets.xlsx 重命名为 EmpDatasets.csv 即可将其转换为 CSV。使用this 进行操作。

      将文件保存为 CSV 后,您可以将其读取为 spark.read.csv(pathToCSV),并且可以提供许多选项,例如:读取/跳过标题或将数据集的架构提供为 spark.read.schema(schema).csv(pathToCSV)

      这里schema 可以按照here 的描述创建,也可以使用spark sql EncodersEncoders.product[case_class_name].schema从案例类中提取

      1. 您可以从列名中删除空格,例如:

      val employeesDFColumns = employeesDF.columns.map(x => col(x.replaceAll(" ", "")))

      并在数据框上应用这些新的列名。

      val employeeDF = employeeDF.select(employeesDFColumns:_*)

      【讨论】:

      • 我只需要将其读取为 excel 文件,我无法转换为 csv 或任何其他文件格式。您能否就阅读/解析 excel 文件提出任何建议?
      • 您用于 excel 的库似乎完全没问题。并且是阅读excel的推荐方法之一。您在使用中遇到了什么问题?
      • 请参考我的问题,我需要为其分配自定义列名并创建一个数据框,如何为这些包含空格的列名编写sql查询?
      猜你喜欢
      • 2020-03-18
      • 2021-05-23
      • 1970-01-01
      • 2021-04-17
      • 2020-09-24
      • 1970-01-01
      • 2020-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多