2016-10-25 8 views
2

データフレームのスキーマをキャストして、いくつかのカラムのタイプを変更したいと思います。 SparkとScalaを使用しています。具体的に、私はその説明を読み、[U]関数として使用しようとしていますSparkとScalaのデータフレームのスキーマをキャスト

:。 「各レコードは、指定した型に上のマップされた新しいデータセットを返します 列をマップするために使用される方法は、の種類によって異なりますU "

原則としてこれは私が欲しいものですが、私はそれを働かせることはできません。ここで

は、データのスキーマが期待されるように https://github.com/apache/spark/blob/master/sql/core/src/test/scala/org/apache/spark/sql/DatasetSuite.scala



    // definition of data 
    val data = Seq(("a", 1), ("b", 2)).toDF("a", "b") 

から取られた簡単な例である:

 

    root 
    |-- a: string (nullable = true) 
    |-- b: integer (nullable = false) 

私はダブルに列「b」をキャストしたいと思います。だから私は、次のことを試してください。



    import session.implicits._; 

    println(" --------------------------- Casting using (String Double)") 

    val data_TupleCast=data.as[(String, Double)] 
    data_TupleCast.show() 
    data_TupleCast.printSchema() 

    println(" --------------------------- Casting using ClassData_Double") 

    case class ClassData_Double(a: String, b: Double) 

    val data_ClassCast= data.as[ClassData_Double] 
    data_ClassCast.show() 
    data_ClassCast.printSchema() 

私は[U]などの定義を理解したように、新しいデータフレームには、次のスキーマ

 

    root 
    |-- a: string (nullable = true) 
    |-- b: double (nullable = false) 

を持っている必要がありますが、出力が

 

    --------------------------- Casting using (String Double) 
    +---+---+ 
    | a| b| 
    +---+---+ 
    | a| 1| 
    | b| 2| 
    +---+---+ 

    root 
    |-- a: string (nullable = true) 
    |-- b: integer (nullable = false) 

    --------------------------- Casting using ClassData_Double 
    +---+---+ 
    | a| b| 
    +---+---+ 
    | a| 1| 
    | b| 2| 
    +---+---+ 

    root 
    |-- a: string (nullable = true) 
    |-- b: integer (nullable = false) 

です列 "b"が二重にキャストされていないことを示す。

私が間違っていることに関するヒントはありますか?

私は以前の記事「Spark SQLのDataFrameで列の種類を変更する方法を知っていますか? (How to change column types in Spark SQL's DataFrame?参照)。私はカラムのタイプを一度に1つずつ変更できることを知っていますが、データ全体のスキーマをワンショットで変更するより一般的なソリューションを探しています(プロセスでスパークを理解しようとしています)。まあ

+0

- 'として[U]' API実際のタイプは変更されませんが、データセットを処理するための型付きAPIを提供するだけです。 'U'は実際の型と一致しなければなりません。実際の型の変更はリンクした質問で説明した' Column.cast'などの変換を介してのみ行うことができます。 –

答えて

4

、機能が連鎖しているためとスパークは、遅延評価を行い、 それは実際にあなたは、このような時に1列を変更するとして、それを書く場合でも、変更一発で全データのスキーマを行います。

代替案として
import spark.implicits._ 

df.withColumn("x", 'x.cast(DoubleType)).withColumn("y", 'y.cast(StringType))... 

、私は次のように、あなたが一度にあなたのキャストを行うためにmapを使用することができます思っている:私はあなたができるとは思わない

df.map{t => (t._1, t._2.asInstanceOf[Double], t._3.asInstanceOf[], ...)} 
+0

提案してくれてありがとう、彼らは私がSOで見つけた他のソリューションに非常によく似ています。また、彼らは私が採用しようとしている解決策と非常によく似ています。それでも、[u]として使用すると非常に便利です。私はエンコーダーでトリックを行うべきかどうか疑問に思っていますが、エンコーダーが必要ない場合(String、Int)という理由が理解できません。 –

関連する問題