【问题标题】:Spark read multiple CSV file with header only in first fileSpark仅在第一个文件中读取带有标题的多个CSV文件
【发布时间】:2018-11-06 14:18:47
【问题描述】:

我想从 spark 读取多个 CSV 文件,但标题只存在于第一个文件中,例如:

文件 1:

id, name
1, A
2, B
3, C

文件 2:

4, D
5, E
6, F

PS:我想使用 java API 来做到这一点

【问题讨论】:

    标签: java apache-spark


    【解决方案1】:

    您可以使用 header=true 并使用 inferSchema=true 从您拥有标题的文件中获取正确的数据类型。然后将此模式类型转换为 Java 中的 StructType 并使用它来导入其他没有标题的 csv 文件。这是在 spark 版本 2.3.2 中测试的

        import org.apache.spark.sql.Dataset;
        import org.apache.spark.sql.Row;
        import org.apache.spark.sql.SparkSession;
    
    
        SparkSession spark = SparkSession.builder()
            .appName("SimpleApp")
            .master("local")
            .getOrCreate();
    
      // Use this to get the headers automatically
        Dataset<Row> csvData = sparkSession.read()
           .format("csv")
           .option("header","true")
           .option("inferSchema","true")
           .load("C:\\MyData\\numData.csv");
    
        csvData.printSchema();
    

    【讨论】:

      【解决方案2】:

      如果不是全部,您肯定会知道具有标题的一个文件的名称。 在这种情况下,从现有的answer 扩展,假设带有标题的文件名是h.csv

      val sqlContext = new SQLContext(sc)
      
      val file1DF = sqlContext
        .read
        .format("csv")
        .option("header", "true")
        .load("<path to folder>/h.csv")
      
      val schema = file1.schema
      
      val file2DF = sqlContext
        .read
        .format("csv")
        .schema(schema)
        .load("<path to folder>/{[^h],h[^.]}*.csv")
      

      现在,提供的正则表达式功能并不太精致。但是,我不认为 Spark DataFrameReader.load public api 为我们提供了排除特定名称的任何强大方法。

      更多指向此 API 接受的 glob 模式的链接位于@此answer

      hadoop 的内部 API 似乎允许过滤(下图来自上述答案中链接的相关书籍部分):

      对于您的情况,您可能希望使用简单名称的标题来命名您的文件,例如h.csv 和上面代码中第二部分的正则表达式可能有{[^h],h[^.]}*.csv,以包括所有不以h 开头的文件,或者如果它们以h 开头,那么第二个字符不是.

      【讨论】:

      • @Sandeep,这有帮助吗?
      【解决方案3】:

      您需要执行以下操作

      Scala 解决方案:

      val sqlContext = new SQLContext(sc)
      
      val file1DF = sqlContext
        .read
        .format("csv")
        .option("header", "true")
        .load("file1.csv")
      
      val schema = file1.schema
      
      val file2DF = sqlContext
        .read
        .format("csv")
        .schema(schema)
        .load("file2.csv")
      

      Java 将出现类似的例外情况,您需要将 StructType 用于架构。

      DataFrame file1DF = sqlContext.read()....;
      StructType schema = file1DF.schema();
      DataFrame file2DF = sqlContext.read()....schema(schema)....;
      

      【讨论】:

      • 那肯定行得通,但我正在寻找一种适用于路径中所有文件的通用解决方案。另外,我不知道路径中的文件数。因此无法单独读取文件。
      猜你喜欢
      • 1970-01-01
      • 2019-04-03
      • 1970-01-01
      • 1970-01-01
      • 2016-12-21
      • 1970-01-01
      • 1970-01-01
      • 2022-01-16
      • 1970-01-01
      相关资源
      最近更新 更多