Разделение файла .ttl или .nt - Spark Scala - PullRequest
1 голос
/ 12 марта 2019

Я новичок в scala, и мне нужно построчно читать файл ttl, разбивать его на определенный разделитель и извлекать значения, чтобы поместить их в соответствующие столбцы в фрейме данных.

< http://website/Jimmy_Carter> <http://web/name> "James Earl Carter, Jr."@ko .
< http://website/Jimmy_Car> <http://web/country> <http://website/United_States> .
< http://website/Jimmy_Car> <http://web/birthPlace> <http://web/Georgia_(US)> .

Я хочу получить этот вывод

+-------------------------------+---------------------------+-----------------------------
|S                              |P                          |O                                                             |
+-------------------------------+---------------------------+-----------------------------

|http://website/Jimmy_Car       |http://web/name            |"James Earl Carter                                                       |
|http:///website/Jimmy_Car      |http://web/country         |http://web/country                   |
|http://website/Jimmy_Car       |http://web/birthPlace      |http://web/Georgia_(US)             |
|

Я попробовал этот код

case class T(S: Option[String], P: Option[String],O:Option[String])


 val triples = sc.textFile("triples_test.ttl").map(_.split(" |\\< |\\> |\\ . ")).map(p => 
  T(Try(p(0).toString()).toOption,Try(p(1).toString()).toOption,Try(p(2).toString()).toOption)).toDF()

И я получил этот результат

    +-------------------------------+---------------------------+-----------------------------
|S                              |P                          |O                                                             |
+-------------------------------+---------------------------+-----------------------------

|<http://website/Jimmy_Car       |<http://web/name            |"James                                                       |
|<http:///website/Jimmy_Car      |<http://web/country         |<http://web/country                   |
|<http://website/Jimmy_Car       |<http://web/birthPlace      |<http://web/Georgia_(US) 

Чтобы удалить разделитель «<» в начале каждой тройки, я добавил «| <» к разбиению </p>

 val triples = sc.textFile("triples_test.ttl").map(_.split(" |\\< |\\> |\\ . |<")).map(p => 
  T(Try(p(0).toString()).toOption,Try(p(1).toString()).toOption,Try(p(2).toString()).toOption)).toDF()

И у меня был такой результат

    +-------------------------------+---------------------------+-----------------------------
|S                              |P                          |O                                                             |
+-------------------------------+---------------------------+-----------------------------

|                                |http://web/name            |                                                      |
|                                |http://web/country         |                   |
|                                |http://web/birthPlace      | 

Как я могу решить эту проблему

Ответы [ 2 ]

0 голосов
/ 14 марта 2019

Вы не можете прочитать файл Turtle, как это. Кроме того, регулярные выражения - это очень наивный способ чтения N-триплетов. Не изобретай колесо и используй https://github.com/banana-rdf/banana-rdf

0 голосов
/ 12 марта 2019

Ниже приведен ответ в случае, если неясно, как заменить ваш код функциональностью встроенного регулярного выражения в Spark. Хотя вы должны быть уверены, что понимаете, как работает регулярное выражение, прежде чем использовать этот подход.

val df = Seq(
        ("< http://website/Jimmy_Carter>", "<http://web/name>", "\"James Earl Carter, Jr.\"@ko .\""),
        ("< http://website/Jimmy_Car>", "<http://web/country>", "<http://website/United_States> ."),
        ("< http://website/Jimmy_Car>", "<http://web/birthPlace>", "<http://web/Georgia_(US)> .")
    ).toDF("S", "P", "O")

val url_regex = """^(?:"|<{1}\s?)(.*)(?:>(?:\s\.)?|,\s.*)$"""
val dfA = df.withColumn("S", regexp_extract($"S", url_regex, 1))
            .withColumn("P", regexp_extract($"P", url_regex, 1))
            .withColumn("O", regexp_extract($"O", url_regex, 1))

Будет выведено:

+---------------------------+---------------------+----------------------------+
|S                          |P                    |O                           |
+---------------------------+---------------------+----------------------------+
|http://website/Jimmy_Carter|http://web/name      |James Earl Carter           |
|http://website/Jimmy_Car   |http://web/country   |http://website/United_States|
|http://website/Jimmy_Car   |http://web/birthPlace|http://web/Georgia_(US)     |
+---------------------------+---------------------+----------------------------+

Просто небольшое объяснение, как работает регулярное выражение, даже если это не тема поста.

  1. (?:"|<{1}\s?) Определите строки, которые начинаются с " или < или <
  2. (.*) извлечь содержимое матчей в 1-ю группу
  3. (?:>(?:\s\.)?|,\s.*) Определите строки, которые заканчиваются либо >, либо > ., либо ,\s.* последним для случая с Джеймсом Эрлом
...