Скала Спарк. Создать объект со значением по умолчанию с помощью DataType - PullRequest
0 голосов
/ 17 июня 2019

У меня есть список объектов org.apache.spark.sql.types.DataType, скажем,
val tps = [FloatType, LongType, FloatType, DoubleType], который я получаю из фрейма данных следующим образом:

val tps = dataFrame.schema
      .filter(f => f.dataType.isInstanceOf[NumericType])
      .map(f => f.dataType)

и для каждоговведите в этом списке мне нужно создать объект соответствующего типа со значением по умолчанию :
[0.0, 0l, 0.0, 0.0].Как я могу это сделать?

Я пытался сделать

tps.map(t => t.getClass.newInstance())

, но это не сработало, потому что частные члены (can not access a member of class org.apache.spark.sql.types.LongType$ with modifiers "private") и потому, что этот оператор пытается создать объектыDataType, и мне нужны объекты соответствующих типов для них.

Я довольно новичок в scala, кто-то может помочь?

Ответы [ 2 ]

1 голос
/ 17 июня 2019

Я следовал подсказкам из ответа @ fd8s0, и вот что я придумал:

  def mapToDefault(dataType: DataType): Number = {
    val defaultVal = 0.0
    dataType match {
      case ShortType => defaultVal.toShort
      case IntegerType => defaultVal.toInt
      case LongType => defaultVal.toLong
      case FloatType => defaultVal.toFloat
      case DoubleType => defaultVal.toDouble
      case t => null
    }
  }

...

val defaultValues = dataFrame.schema
    .filter(f => f.dataType.isInstanceOf[NumericType])
    .map(column => mapToDefault(column.dataType))

Таким образом, метод mapToDefault выполнит работу по созданию экземпляра данного DataType со значением по умолчанию (длятолько числовые типы, в моем случае).

1 голос
/ 17 июня 2019

У меня для тестирования есть что-то вроде этого

object RowSampleMaker {

  var makerRunNumber = 1

  def apply(schema: StructType): Row = new GenericRowWithSchema(schema.map(field => {
      makerRunNumber += 1
      field.dataType match {
        case ShortType => makerRunNumber.toShort
        case IntegerType => makerRunNumber
        case LongType => makerRunNumber.toLong
        case FloatType => makerRunNumber.toFloat
        case DecimalType() => d(makerRunNumber)
        case DateType => new Date(System.currentTimeMillis)
        case TimestampType => new Timestamp(System.currentTimeMillis)
        case StringType => s"arbitrary-$makerRunNumber"
        case BooleanType => false
        case StructType(fields) => apply(StructType(fields))
        case t => throw new Exception(s"Maker doesn't support generating $t")
      }
    }).toArray, schema)

  implicit class RowManipulation(row: Row) {

    def update(fieldName: String, value: Any): Row = new GenericRowWithSchema(
      row.toSeq.updated(row.fieldIndex(fieldName), value).toArray,
      row.schema
    )
  }
}

Вы можете добавлять типы и заменять случайность на 0. Или иметь другой вызов метода .zero, который возвращает все нейтральные значения. Метод обновления неявного класса заключается в том, что я обычно обновляю пару значений для целей тестирования.

Вы бы позвонили RowSampleMaker(schema).update("field1", value1).update("field2", value2) Для каждой строки, которую вы хотите сгенерировать, а затем создать кадр данных из этого

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...