pyspark не распознает шаблон MMM dateFormat в spark.read.load() для таких дат, как 1989Dec31 и 31Dec1989

У меня возникла очень странная проблема с pyspark в macOS Sierra. Моя цель - анализировать даты в формате ddMMMyyyy (например: 31Dec1989), но получать ошибки. Я использую Spark 2.0.1, Python 2.7.10 и Java 1.8.0_101. Я также пытался использовать Anaconda 4.2.0 (она поставляется с Python 2.7.12), но тоже получаю ошибки.

Тот же код на Ubuntu Server 15.04 с той же версией Java и Python 2.7.9 работает без ошибок.

В официальной документации о spark.read.load() говорится:

dateFormat — задает строку, указывающую формат даты. Пользовательские форматы даты следуют форматам в java.text.SimpleDateFormat. Это относится к типу даты. Если установлено None, используется значение по умолчанию, yyyy-MM-dd.

В официальной документации по Java говорится о MMM как о правильный формат для анализа названий месяцев, таких как Jan, Dec и т. д., но он выдает много ошибок, начинающихся с java.lang.IllegalArgumentException. В документации указано, что LLL тоже можно использовать, но pyspark не распознает его и выдает pyspark.sql.utils.IllegalArgumentException: u'Illegal pattern component: LLL'.

Я знаю другое решение для dateFormat, но это самый быстрый способ анализа данных и самый простой код. Что мне здесь не хватает?

Чтобы запустить следующие примеры, вам просто нужно поместить test.csv и test.py в один и тот же каталог, а затем запустить <spark-bin-directory>/spark-submit <working-directory>/test.py.

Мой тестовый пример с использованием формата ddMMMyyyy

У меня есть текстовый файл с именем test.csv, содержащий следующие две строки:

col1
31Dec1989

и код следующий:

from pyspark.sql import SparkSession
from pyspark.sql.types import *

spark = SparkSession \
    .builder \
    .appName("My app") \
    .config("spark.some.config.option", "some-value") \
    .getOrCreate()

struct = StructType([StructField("column", DateType())])
df = spark.read.load(   "test.csv", \
                            schema=struct, \
                            format="csv", \
                            sep=",", \
                            header="true", \
                            dateFormat="ddMMMyyyy", \
                            mode="FAILFAST")
df.show()

Я получаю ошибки. Я также безуспешно пытался переместить название месяца до или после дня и года (например: 1989Dec31 и yyyyMMMdd).

Рабочий пример с использованием формата ddMMyyyy

Этот пример идентичен предыдущему, за исключением формата даты. test.csv теперь содержит:

col1
31121989

Следующий код выводит содержимое test.csv:

from pyspark.sql import SparkSession
from pyspark.sql.types import *

spark = SparkSession \
    .builder \
    .appName("My app") \
    .config("spark.some.config.option", "some-value") \
    .getOrCreate()

struct = StructType([StructField("column", DateType())])
df = spark.read.load(   "test.csv", \
                            schema=struct, \
                            format="csv", \
                            sep=",", \
                            header="true", \
                            dateFormat="ddMMyyyy", \
                            mode="FAILFAST")
df.show()

Вывод следующий (я опускаю различные подробные строки):

+----------+
|    column|
+----------+
|1989-12-31|
+----------+

ОБНОВЛЕНИЕ1

Я сделал простой класс Java, который использует java.text.SimpleDateFormat:

import java.text.*;
import java.util.Date;

class testSimpleDateFormat 
{
    public static void main(String[] args) 
    {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMMdd");
        String dateString = "1989Dec31";

        try {
            Date parsed = format.parse(dateString);
            System.out.println(parsed.toString());
        }
        catch(ParseException pe) {
            System.out.println("ERROR: Cannot parse \"" + dateString + "\"");
        }       
    }
}

Этот код не работает в моей среде и выдает эту ошибку:

java.text.ParseException: Unparseable date: "1989Dec31"

но отлично работает в другой системе (Ubuntu 15.04). Это похоже на проблему с Java, но я не знаю, как ее решить. Я установил последнюю доступную версию Java, и все мое программное обеспечение было обновлено.

Любые идеи?


ОБНОВЛЕНИЕ 2

Я нашел, как заставить его работать на чистой Java, указав Locale.US:

import java.text.*;
import java.util.Date;
import java.util.*;

class HelloWorldApp 
{
    public static void main(String[] args) 
    {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMMdd", Locale.US);
        String dateString = "1989Dec31";

        try {
            Date parsed = format.parse(dateString);
            System.out.println(parsed.toString());
        }
        catch(ParseException pe) {
            System.out.println(pe);
            System.out.println("ERROR: Cannot parse \"" + dateString + "\"");
        }       
    }
}

Теперь возникает вопрос: как указать локаль Java в pyspark?


person pietrop    schedule 12.10.2016    source источник


Ответы (3)


Вероятно, стоит отметить, что это было решено в списке рассылки Spark 24 октября 2016 г. Согласно оригинальному постеру:

Это работало без установки других параметров: spark/bin/spark-submit --conf "spark.driver.extraJavaOptions=-Duser.language=en" test.py

и было сообщено как SPARK-18076 (исправлена ​​локаль по умолчанию, используемая в DateFormat, NumberFormat на Locale.US) против Spark 2.0.1 и была устранена в Spark 2.1.0.

Кроме того, хотя описанный выше обходной путь (передача --conf "spark.driver.extraJavaOptions=-Duser.language=en") для конкретной проблемы, поднятой отправителем, больше не требуется при использовании Spark 2.1.0, заметным побочным эффектом является то, что для пользователей Spark 2.1.0 вы больше не можете передать что-либо. например --conf "spark.driver.extraJavaOptions=-Duser.language=fr", если вы хотите проанализировать неанглийскую дату, например. «31 мая 1989 года».

Фактически, начиная со Spark 2.1.0, при использовании spark.read() для загрузки csv я думаю, что больше невозможно использовать параметр dateFormat для анализа даты, такой как «31mai1989», даже если ваш язык по умолчанию — французский. Я дошел до того, что изменил регион и язык по умолчанию в своей ОС на французский и передал практически все перестановки настроек локали, о которых только мог подумать, т.е.

JAVA_OPTS="-Duser.language=fr -Duser.country=FR -Duser.region=FR" \
JAVA_ARGS="-Duser.language=fr -Duser.country=FR -Duser.region=FR" \
LC_ALL=fr_FR.UTF-8 \
spark-submit \
--conf "spark.driver.extraJavaOptions=-Duser.country=FR -Duser.language=fr -Duser.region=FR" \
--conf "spark.executor.extraJavaOptions=-Duser.country=FR -Duser.language=fr -Duser.region=FR" \
test.py

безрезультатно, в результате чего

java.lang.IllegalArgumentException
    at java.sql.Date.valueOf(Date.java:143)
    at org.apache.spark.sql.catalyst.util.DateTimeUtils$.stringToTime(DateTimeUtils.scala:137)

Но опять же, это влияет только на синтаксический анализ неанглийских дат в Spark 2.1.0.

person eddies    schedule 16.03.2017

Вы уже определили проблему как одну из локалей в JVM Spark. Вы можете проверить настройки страны и языка по умолчанию, используемые вашей JVM Spark, перейдя по адресу http://localhost:4040/environment/ после запуска искровой оболочки. Найдите «user.language» и «user.country» в разделе «Свойства системы». Это должно быть US и en.

Вы можете изменить их так, если это необходимо.

Вариант 1. Отредактируйте файл spark-defaults.conf в папке {SPARK_HOME}/conf. Добавьте следующие настройки:

spark.executor.extraJavaOptions  -Duser.country=US -Duser.language=en
spark.driver.extraJavaOptions -Duser.country=US -Duser.language=en

Вариант 2. Передайте параметры pyspark в качестве параметра командной строки.

  $pyspark  --conf spark.driver.extraJavaOptions="-Duser.country=US,-Duser.language=en" spark.executor.extraJavaOptions="-Duser.country=US,-Duser.language=en"

Вариант 3. Измените язык и регион в Mac OS. Например, Какие настройки в Mac OS X влияет на `Locale` и `Calendar` внутри Java?

P.S. - Я только проверил, что Вариант 1 работает. Я не пробовал другие 2. Более подробная информация о конфигурации Spark находится здесь - http://spark.apache.org/docs/latest/configuration.html#runtime-environment

person Shankar P S    schedule 14.03.2017

Я не тестировал это, но я бы попробовал следующее:

--conf spark.executor.extraJavaOptions="-Duser.timezone=America/Los_Angeles"

--conf spark.driver.extraJavaOptions="-Duser.timezone=America/Los_Angeles"
person Boggio    schedule 18.03.2017