Переименовать вложенное поле в наборе данных Scala Spark 2.0

Я пытаюсь переименовать вложенное поле в наборе данных классов случаев, используя Spark 2.0. Ниже приведен пример, когда я пытаюсь переименовать «элемент» в «адрес» (сохраняя его вложенность в структуру данных):

df.printSchema
//Current Output:
root
 |-- companyAddresses: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- addressLine: string (nullable = true)
 |    |    |-- addressCity: string (nullable = true)
 |    |    |-- addressCountry: string (nullable = true)
 |    |    |-- url: string (nullable = true)

//Desired Output:
root
 |-- companyAddresses: array (nullable = true)
 |    |-- address: struct (containsNull = true)
 |    |    |-- addressLine: string (nullable = true)
 |    |    |-- addressCity: string (nullable = true)
 |    |    |-- addressCountry: string (nullable = true)
 |    |    |-- url: string (nullable = true)

Для справки, следующее не работает:

df.withColumnRenamed("companyAddresses.element","companyAddresses.address") 
df.withColumnRenamed("companyAddresses.element","address") 

person Nick    schedule 22.08.2016    source источник
comment
stackoverflow.com/questions/35592917/   -  person banjara    schedule 22.08.2016
comment
@shekhar Эта ссылка содержит решения только для плоских наборов данных, проблема, с которой я столкнулся, заключается в том, где вложено поле.   -  person Nick    schedule 22.08.2016


Ответы (2)


То, о чем вы просите здесь, невозможно. companyAddresses — это массив, а element — просто не столбец. Это просто индикатор схемы членов массива. Его нельзя выбрать и нельзя переименовать.

Вы можете только переименовать родительский контейнер:

df.withColumnRenamed("companyAddresses", "foo")

или имена отдельных полей путем изменения схемы. В простых случаях также можно использовать struct и выбрать:

df.select(struct($"foo".as("bar"), $"bar".as("foo")))

но очевидно, что это не применимо здесь.

person zero323    schedule 22.08.2016

Вы можете написать для этого небольшую рекурсивную функцию и использовать карту:

final JavaRDD rdd = df.toJavaRDD().map(row -> ....);


private static void flatDocument(Row input, Map<String,Object> outValues, String fqn)
{
    final StructType schema = input.schema();

    for (StructField field : schema.fields())
    {
        final String fieldName = field.name();

        String key = fqn == null ? fieldName : fqn + "_" + fieldName;

        Object buffer = input.getAs(fieldName);

        if (field.dataType().getClass().equals(StructType.class))
        {
            if (buffer != null) {
                flatDocument((Row) buffer, outValues, key);
            }
        }
        else
        {
            outValues.put(key, buffer);
        }
    }
}

Но вам нужна схема, чтобы преобразовать ее обратно в набор данных:/

person Thomas Decaux    schedule 11.04.2017
comment
Томас, первоначальный ответ был правильным, этот элемент не является столбцом и, следовательно, не может быть переименован. - person Nick; 21.04.2017
comment
Нет, вы сказали, что это невозможно, тогда как это возможно! Я добился этого, используя RDD (разбивая DF, работая над RDD, затем пересобирая DF). - person Thomas Decaux; 22.04.2017