【发布时间】: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
我想从 spark 读取多个 CSV 文件,但标题只存在于第一个文件中,例如:
文件 1:
id, name
1, A
2, B
3, C
文件 2:
4, D
5, E
6, F
PS:我想使用 java API 来做到这一点
【问题讨论】:
标签: java apache-spark
您可以使用 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();
【讨论】:
如果不是全部,您肯定会知道具有标题的一个文件的名称。
在这种情况下,从现有的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 开头,那么第二个字符不是.。
【讨论】:
您需要执行以下操作
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)....;
【讨论】: