我想从spark中读取多个CSV文件,但标题仅出现在第一个文件中,如:
文件1:
id, name
1, A
2, B
3, C
文件2:
4, D
5, E
6, F
PS:我想使用java API来做到这一点
答案 0 :(得分: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();
答案 1 :(得分:0)
您需要执行以下操作
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)....;
答案 2 :(得分:0)
当然,如果不是全部,您肯定会知道具有标题的文件的名称。
在这种情况下,从现有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
开头,那么第二个字符不是.
。