如何将excel数据读入spark / scala中的数据帧

时间:2017-11-22 19:18:22

标签: scala apache-spark dataframe spark-dataframe

我有一个要求在哪里我需要在spark / scala中读取excel文件(扩展名为.xlsx)。我需要创建一个数据框,其中包含从excel读取的数据,并在其上面应用/编写sql查询以进行一些分析。 excel文件有一些列标题/标题,如" time_spend_company(年)"," average_monthly_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")

我想在这些列上应用分组和其他聚合函数,我正面临着如下列这些列的问题,我的要求是在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查询?
  3. 注意:我只需要将其作为excel文件阅读,我无法将其转换为csv或任何其他文件格式。

3 个答案:

答案 0 :(得分:1)

  1. Spark对使用CSV有很好的支持。因此,如果您的Excel文件只有一个工作表,只需将EmpDatasets.xlsx重命名为EmpDatasets.csv即可将其转换为CSV。使用this执行此操作。
  2. 将文件设为CSV后,您可以将其读作spark.read.csv(pathToCSV)并提供许多选项,例如:读取/跳过标题或将数据集的架构提供为spark.read.schema(schema).csv(pathToCSV)

    此处schema可以按照here所述创建,也可以使用spark sql Encoders Encoders.product[case_class_name].schema

    从案例类中提取
    1. 您可以从列名称中删除空格,例如:
    2. val employeesDFColumns = employeesDF.columns.map(x => col(x.replaceAll(" ", "")))

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

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

答案 1 :(得分:1)

问题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是可以的。我也在使用它。也可以有不同的选择。要分配不同的列名,可以使用“结构类型”定义模式,并在将数据加载到数据框期间强制使用它。 e.g

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

答案 2 :(得分:0)

对于版本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>