Предположим, у нас есть последовательность Any
val seq = Seq(1,2,null)
seq: Seq[Any] = List(1, 2, null)
Теперь, если фильтровать ненулевой элемент, будет получена новая последовательность
val cleanSeq = seq.filterNot(_ == null)
cleanSeq: Seq[Any] = List(1, 2)
Теперь я хотел бы получить тот же тип, который я получил бы, если бы создал новую последовательность, например cleanSeq
val seq2 = Seq(1,2)
seq2: Seq[Int] = List(1, 2)
Могу ли я каким-то образом получить Seq[Int]
, начиная с cleanSeq
?
ОБНОВЛЕНИЕ
Предыдущее было только фиктивным примером, и у меня могут быть другие типы, кроме Int
, а также пример сложных типов: Array[Map[String, Float]]
.
Единственное предположение, которое я могу сделать, это то, что у меня есть последовательность, которая может содержать нули. Но другие элементы в последовательности имеют общий супертип, кроме Any
. После удаления нулей я хочу найти общий супертип.
ОБНОВЛЕНИЕ
Вариант использования
Я хочу для создания искрового фрейма данных из столбцов, имеющих имя и значения. Значения хранятся в Seq
. Из типа Seq
я хочу получить схему для фрейма данных.
Определение столбца
import reflect.runtime.universe._
import org.apache.spark.sql.catalyst.ScalaReflection
import org.apache.spark.sql.types._
case class InternalColumn[A: TypeTag](colName: String, col: Seq[A]) {
private def getType: DataType = ScalaReflection.schemaFor[A].dataType
def genStructField: StructField = StructField(colName, getType)
}
Создание фрейма данных:
def createDF[T](data: Seq[T], sch: StructType): DataFrame = {
val dataRow: Seq[Row] = data.map {
case row: Row => row
case prod: Product => Row(prod.productIterator.toSeq: _*)
case d => Row(d)
}
spark.createDataFrame(sc.makeRDD(dataRow), sch)
}
Использование
def createFromColumns(data: Seq[InternalColumn[_]]): DataFrame = {
def loop(schema: StructType, cols: Seq[InternalColumn[_]]): StructType = cols.toList match {
case Nil => schema
case h :: t => loop(schema.add(h.genStructField), t)
}
val sch: StructType = loop(new StructType(), data)
createDF(data.map(_.col).transpose.map(Row.fromSeq), sch)
}
val df = createFromColumns(List(InternalColumn("c1", List(1,2,3)), InternalColumn("c2", List("a", "b", "c"))))
scala> df.show()
+---+---+
| c1| c2|
+---+---+
| 1| a|
| 2| b|
| 3| c|
+---+---+
scala> df.printSchema
root
|-- c1: integer (nullable = true)
|-- c2: string (nullable = true)
Это пока работает неплохо. Но можно создать фрейм данных, в котором есть столбец, содержащий нули. Если столбец с нулевым значением допускает значение NULL, например, он имеет StringType
, он все еще работает.
Проблема возникает, когда у вас есть нули в столбце, который не допускает значения NULL, например:
scala> val df = createFromColumns(List(InternalColumn("c1", List(1,2,null)), InternalColumn("c2", List("a", "b", "c"))))
java.lang.UnsupportedOperationException: Schema for type Any is not supported
Это причина, по которой я хочу вывести тип последовательности, когда я удалил все нули.