С учетом кадра данных со столбцом массивов целых чисел разных размеров:
scala> sampleDf.show()
+------------+
| arrays|
+------------+
|[15, 16, 17]|
|[15, 16, 17]|
| [14]|
| [11]|
| [11]|
+------------+
scala> sampleDf.printSchema()
root
|-- arrays: array (nullable = true)
| |-- element: integer (containsNull = true)
Я хотел бы создать новый столбец со случайно выбранным элементом в каждом массиве.Я пробовал два решения:
1. При использовании UDF:
import scala.util.Random
def getRandomElement(arr: Array[Int]): Int = {
arr(Random.nextInt(arr.size))
}
val getRandomElementUdf = udf{arr: Array[Int] => getRandomElement(arr)}
sampleDf.withColumn("randomItem", getRandomElementUdf('arrays)).show
вылетает в последней строке с длинным сообщением об ошибке: (извлекает)
...
Caused by: org.apache.spark.SparkException: Failed to execute user defined function($anonfun$1: (array<int>) => int)
...
Caused by: java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot be cast to [I
Имеюпробовал с альтернативным определением udf:
val getRandomElementUdf = udf[Int, Array[Int]] (getRandomElement)
но я получаю ту же ошибку.
2. Второй метод путем создания промежуточных столбцов со случайным индексом в диапазоне соответствующего массива:
// Return a dataframe with a column with random index from column of Arrays with different sizes
def choice(df: DataFrame, colName: String): DataFrame = {
df.withColumn("array_size", size(col(colName)))
.withColumn("random_idx", least('array_size, floor(rand * 'array_size)))
}
choice(sampleDf, "arrays").show
выводит:
+------------+----------+----------+
| arrays|array_size|random_idx|
+------------+----------+----------+
|[15, 16, 17]| 3| 2|
|[15, 16, 17]| 3| 1|
| [14]| 1| 0|
| [11]| 1| 0|
| [11]| 1| 0|
+------------+----------+----------+
и в идеале мы хотели бы использовать столбец random_idx
для выбора элемента в столбце arrays
, вид:
sampleDf.withColumn("choosen_item", 'arrays.getItem('random_idx))
К сожалению, getItem
не может принять столбец в качестве аргумента.
Любые предложения приветствуются.