Spark没有读取第一行中具有空值的列

时间:2017-08-10 06:18:07

标签: apache-spark apache-spark-sql apache-spark-2.0 spark-csv

以下是我的csv文件中的内容:

A1,B1,C1
A2,B2,C2,D1
A3,B3,C3,D2,E1
A4,B4,C4,D3
A5,B5,C5,,E2

因此,第一行有5列,但只有3个值。

我使用以下命令阅读它:

val csvDF : DataFrame = spark.read
.option("header", "false")
.option("delimiter", ",")
.option("inferSchema", "false")
.csv("file.csv") 

以下是我使用csvDF.show()

的内容
+---+---+---+
|_c0|_c1|_c2|
+---+---+---+
| A1| B1| C1|
| A2| B2| C2|
| A3| B3| C3|
| A4| B4| C4|
| A5| B5| C5|
+---+---+---+

如何读取所有列中的所有数据?

3 个答案:

答案 0 :(得分:1)

基本上,您的csv文件格式不正确,因为它在每行中没有相同数量的列,如果您想用spark.read.csv读取它,则需要这样。但是,您可以使用spark.read.textFile读取它,然后解析每一行。

据我了解,您事先并不知道列数,因此您希望代码处理任意数量的列。为此,您需要确定数据集中的最大列数,因此您需要对数据集进行两次传递。

对于这个特殊问题,我实际上会使用RDD而不是DataFrames或Datasets,如下所示:

val data  = spark.read.textFile("file.csv").rdd

val rdd = data.map(s => (s, s.split(",").length)).cache
val maxColumns = rdd.map(_._2).max()

val x = rdd
  .map(row => {
    val rowData = row._1.split(",")
    val extraColumns = Array.ofDim[String](maxColumns - rowData.length)
    Row((rowData ++ extraColumns).toList:_*)
  })

希望有所帮助:)

答案 1 :(得分:0)

您可以将其读作仅包含一列的数据集(例如,使用其他分隔符):

var df = spark.read.format("csv").option("delimiter",";").load("test.csv")
df.show()

+--------------+
|           _c0|
+--------------+
|      A1,B1,C1|
|   A2,B2,C2,D1|
|A3,B3,C3,D2,E1|
|   A4,B4,C4,D3|
|  A5,B5,C5,,E2|
+--------------+

然后,您可以使用this answer手动将列拆分为五个,当元素不存在时,这将添加 null 值:

var csvDF = df.withColumn("_tmp",split($"_c0",",")).select(
    $"_tmp".getItem(0).as("col1"),
    $"_tmp".getItem(1).as("col2"),
    $"_tmp".getItem(2).as("col3"),
    $"_tmp".getItem(3).as("col4"),
    $"_tmp".getItem(4).as("col5")
)
csvDF.show()

+----+----+----+----+----+
|col1|col2|col3|col4|col5|
+----+----+----+----+----+
|  A1|  B1|  C1|null|null|
|  A2|  B2|  C2|  D1|null|
|  A3|  B3|  C3|  D2|  E1|
|  A4|  B4|  C4|  D3|null|
|  A5|  B5|  C5|    |  E2|
+----+----+----+----+----+

答案 2 :(得分:0)

如果列dataTypes和列数已知,那么您可以定义schema并在将schema文件读为csv时应用dataframe。下面我将所有五列定义为stringType

val schema = StructType(Seq(
  StructField("col1", StringType, true),
  StructField("col2", StringType, true),
  StructField("col3", StringType, true),
  StructField("col4", StringType, true),
  StructField("col5", StringType, true)))

val csvDF : DataFrame = sqlContext.read
  .option("header", "false")
  .option("delimiter", ",")
  .option("inferSchema", "false")
  .schema(schema)
  .csv("file.csv")

你应该dataframe

+----+----+----+----+----+
|col1|col2|col3|col4|col5|
+----+----+----+----+----+
|A1  |B1  |C1  |null|null|
|A2  |B2  |C2  |D1  |null|
|A3  |B3  |C3  |D2  |E1  |
|A4  |B4  |C4  |D3  |null|
|A5  |B5  |C5  |null|E2  |
+----+----+----+----+----+