Прочитайте CSV с последним столбцом как массив значений (и значения находятся внутри круглых скобок и разделены запятой) в Spark

У меня есть файл CSV, в котором последний столбец находится внутри круглых скобок, а значения разделены запятыми. Количество значений в последнем столбце является переменным. Когда я читаю их как Dataframe с некоторыми именами столбцов следующим образом, я получаю Exception in thread "main" java.lang.IllegalArgumentException: requirement failed: The number of columns doesn't match. Мой файл CSV выглядит так

a1,b1,true,2017-05-16T07:00:41.0000000,2.5,(c1,d1,e1)
a2,b2,true,2017-05-26T07:00:42.0000000,0.5,(c2,d2,e2,f2,g2)
a2,b2,true,2017-05-26T07:00:42.0000000,0.5,(c2)
a2,b2,true,2017-05-26T07:00:42.0000000,0.5,(c2,d2)
a2,b2,true,2017-05-26T07:00:42.0000000,0.5,(c2,d2,e2)
a2,b2,true,2017-05-26T07:00:42.0000000,0.5,(c2,d2,e2,k2,f2)

наконец, я хочу что-то вроде этого:

root
 |-- MId: string (nullable = true)
 |-- PId: string (nullable = true)
 |-- IsTeacher: boolean(nullable = true)
 |-- STime: datetype(nullable = true)
 |-- TotalMinutes: double(nullable = true)
 |-- SomeArrayHeader: array<string>(nullable = true)

Я написал следующий код до сих пор:

val infoDF =
  sqlContext.read.format("csv")
    .option("header", "false")
    .load(inputPath)
    .toDF(
      "MId",
      "PId",
      "IsTeacher",
      "STime",
      "TotalMinutes",
      "SomeArrayHeader")

Я подумал о том, чтобы прочитать их, не указывая имена столбцов, а затем преобразовать столбцы, которые находятся после 5-го столбца, в тип массива. Но тогда у меня проблемы со скобками. Есть ли способ сделать это, читая и сообщая, что поля внутри скобок на самом деле являются одним полем массива типов.


person Sunil Kumar    schedule 12.10.2018    source источник
comment
это неправильный контент csv, последний столбец должен быть заключен в двойные кавычки.. вы не можете прочитать тип массива с помощью csv.. проверит, есть ли обходной путь   -  person stack0114106    schedule 12.10.2018
comment
Да, я знаю. Но мой файл выглядит только так. Если бы он был в кавычках, не было бы проблем с чтением csv, но его нет в кавычках.   -  person Sunil Kumar    schedule 12.10.2018


Ответы (1)


Ok. Решение только тактическое для вашего случая. Ниже один работал для меня

  val df = spark.read.option("quote", "(").csv("in/staff.csv").toDF(
    "MId",
    "PId",
    "IsTeacher",
    "STime",
    "TotalMinutes",
    "arr")
  df.show()
  val df2 = df.withColumn("arr",split(regexp_replace('arr,"[)]",""),","))
  df2.printSchema()
  df2.show()

Вывод:

+---+---+---------+--------------------+------------+---------------+
|MId|PId|IsTeacher|               STime|TotalMinutes|            arr|
+---+---+---------+--------------------+------------+---------------+
| a1| b1|     true|2017-05-16T07:00:...|         2.5|      c1,d1,e1)|
| a2| b2|     true|2017-05-26T07:00:...|         0.5|c2,d2,e2,f2,g2)|
| a2| b2|     true|2017-05-26T07:00:...|         0.5|            c2)|
| a2| b2|     true|2017-05-26T07:00:...|         0.5|         c2,d2)|
| a2| b2|     true|2017-05-26T07:00:...|         0.5|      c2,d2,e2)|
| a2| b2|     true|2017-05-26T07:00:...|         0.5|c2,d2,e2,k2,f2)|
+---+---+---------+--------------------+------------+---------------+

root
 |-- MId: string (nullable = true)
 |-- PId: string (nullable = true)
 |-- IsTeacher: string (nullable = true)
 |-- STime: string (nullable = true)
 |-- TotalMinutes: string (nullable = true)
 |-- arr: array (nullable = true)
 |    |-- element: string (containsNull = true)

+---+---+---------+--------------------+------------+--------------------+
|MId|PId|IsTeacher|               STime|TotalMinutes|                 arr|
+---+---+---------+--------------------+------------+--------------------+
| a1| b1|     true|2017-05-16T07:00:...|         2.5|        [c1, d1, e1]|
| a2| b2|     true|2017-05-26T07:00:...|         0.5|[c2, d2, e2, f2, g2]|
| a2| b2|     true|2017-05-26T07:00:...|         0.5|                [c2]|
| a2| b2|     true|2017-05-26T07:00:...|         0.5|            [c2, d2]|
| a2| b2|     true|2017-05-26T07:00:...|         0.5|        [c2, d2, e2]|
| a2| b2|     true|2017-05-26T07:00:...|         0.5|[c2, d2, e2, k2, f2]|
+---+---+---------+--------------------+------------+--------------------+
person stack0114106    schedule 12.10.2018
comment
Спасибо! Что там делают кавычки? У меня огромные файлы в ГБ, есть ли проблемы с производительностью? - person Sunil Kumar; 12.10.2018
comment
цитата - это функция синтаксического анализатора csv - когда появляется этот символ кавычки, синтаксический анализатор считывает содержимое до следующего символа кавычки в один столбец. Таким образом, нам разрешено иметь разделители в наших данных при условии, что они заключены в кавычки. Символ кавычек по умолчанию - двойные кавычки. Парсеры CSV не допускают более одного символа для функции кавычек. В нашем случае у нас есть ( и ), поэтому я дал (при чтении и в df2 я удалил ). Нам повезло, что этот столбец находится последним, поэтому он читается до конца строки. - person stack0114106; 12.10.2018
comment
Таким образом, цитата здесь будет рассматривать кавычки по умолчанию () как одну из кавычек? И это тоже будет относиться ( как одна из цитат, не так ли? - person Sunil Kumar; 12.10.2018
comment
в нашем случае мы переопределили с помощью (, у вас может быть только один символ кавычки.. - person stack0114106; 12.10.2018