тип карты pyspark содержит дубликаты ключей

#python #apache-spark #pyspark #apache-spark-sql

#python #apache-spark #pyspark #apache-spark-sql

Вопрос:

Может ли кто-нибудь помочь мне понять, почему тип карты в pyspark может содержать дубликаты ключей?

Примером может быть:

 # generate a sample dataframe
# the `field` column is an array of struct with value a and value b
# the goal is to create a map from a -> b 

df = spark.createDataFrame([{
    'field': [Row(a=1, b=2), Row(a=1, b=3)],
}])


# above code would generate a dataframe like this
 ---------------- 
|           field|
 ---------------- 
|[[1, 2], [1, 3]]|
 ---------------- 

# with schema
root
 |-- field: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- a: long (nullable = true)
 |    |    |-- b: long (nullable = true)

 

Затем я применил map_from_entries этот фрейм данных, пытаясь собрать уникальные a->b пары. Я ожидал, что карта будет содержать уникальные ключи, то есть {1 -> 3} в данном случае. Тем не менее, я получаю {1 -> 2, 1 -> 3} перед сбором. Это противоречит общей идее map типа.

 import pyspark.sql.functions as F
df.select(F.map_from_entries("field"))

# the result is
 ----------------------- 
|map_from_entries(field)|
 ----------------------- 
|       [1 -> 2, 1 -> 3]|
 ----------------------- 
 

Я также попытался применить F.map_keys() к этому полю и получил [1, 1] в результате. Однако, когда я собираю этот фрейм данных, я смог получить результат без дубликатов ключей:

 df.select(F.map_from_entries("field")).collect()

# result
[Row(map_from_entries(field)={1: 3})]
 

Это вызывает некоторое неожиданное поведение в моей работе spark, и я был бы очень признателен, если бы кто-нибудь помог мне понять, почему pyspark ведет себя таким образом. Это ошибка или по замыслу?

Комментарии:

1. пожалуйста, вставьте пример кода для создания df с полем столбца, это поможет нам понять и предоставить решение более структурированным способом . Также, если код находится в pyspark, можете ли вы попробовать использовать функцию create_map .

2. @AdityaVikramSingh привет, Адитья, спасибо за ответ. я обновил описание фрагментом кода для генерации фрейма данных.

Ответ №1:

Это восходит к реализации карт в Scala: https://www.scala-lang.org/api/2.12.2/scala/collection/immutable/List.html#toMap[T,U]:scala.collection.Map[T,U]

Дубликаты ключей будут перезаписаны более поздними ключами: если это неупорядоченная коллекция, какой ключ находится в результирующей карте, не определено

Поэтому карта 1-> 3 перезаписывает 1-> 2. Это разработанное поведение, а не ошибка.

Комментарии:

1. спасибо за ссылку. я понимаю, почему 1-> 3 сохраняется при сборе результата. мой вопрос заключался в том, почему оба ключа хранятся перед сбором.

2. Я предполагаю, что это ошибка в Spark 2.4. В Spark 3.0 я получаю сообщение об ошибке при вызове df.select: Duplicate map key 1 was found, please check the input data. If you want to remove the duplicated keys, you can set spark.sql.mapKeyDedupPolicy to LAST_WIN so that the key inserted at last takes precedence.