Spark SQL中的RDD與DataFrame轉換

yunqiublog發表於2019-08-12

一.第一種方式RDD轉化為DataFrame

1.官網

2.解釋


反射
把schema資訊全部定義在case class 類裡面

3.程式碼


package core
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.types.StructType
object Test {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder()
      .appName("Test")
      .master("local[2]")
      .getOrCreate()
    val mess = spark.sparkContext.textFile("file:///D:\\test\\person.txt")
    import spark.implicits._
    val result = mess.map(_.split(",")).map(x => Info(x(0).toInt,x(1),x(2).toInt)).toDF()
   // result.map(x => x(0)).show() //在1.x 版本是可以的 在2.x不可以需要價格rdd
    result.rdd.map(x => x(0)).collect().foreach(println)
    result.rdd.map(x => x.getAs[Int]("id")).collect().foreach(println)
  }
}
case class Info(id:Int,name:String,age:Int)

4.注意事項


注意2.2版本以前 類的構造方法引數有限
在2.2後沒有限制了

二.第二種轉換方式

1.官網

2.解釋


制定scheme資訊 就是程式設計的方式   作用到Row 上面

3.步驟

4.步驟解釋


從原有的RDD轉化 ,類似於textFile
一個StructType匹配Row裡面的資料結構(幾列),就是幾個StructField 
通過createDataFrame  把schema與RDD關聯上

5.原始碼解釋StructType

6.原始碼解釋


StructField 可以理解為一列
StructType  包含  1-n 個StructField

7.最終程式碼


package core
import org.apache.spark.sql.types.{IntegerType, StringType, StructField, StructType}
import org.apache.spark.sql.{Row, SparkSession}
object TestRDD2 {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder()
      .appName("TestRDD2")
      .master("local[2]")
      .getOrCreate()
    val mess = spark.sparkContext.textFile("file:///D:\\test\\person.txt")
    val result = mess.map(_.split(",")).map(x => Row(x(0).toInt, x(1), x(2).toInt))
    //工作中這樣寫
    val structType = new StructType(
      Array(
          StructField("id", IntegerType, true),
          StructField("name", StringType, true),
          StructField("age", IntegerType, true)
      )
    )
    val schema = StructType(structType)
    val info = spark.createDataFrame(result,schema)
    info.show()
  }
}

8.經典錯誤

9.原因解決


自己定義的schema資訊與Row中的資訊不匹配
val result = mess.map(_.split(",")).map(x => Row(x(0), x(1), x(2)))
//工作中這樣寫
val structType = new StructType(
  Array(
      StructField("id", IntegerType, true),
      StructField("name", StringType, true),
      StructField("age", IntegerType, true)
  )
)
上面的是string 要的是int ,一定要注意因為會經常出錯要轉化型別
val result = mess.map(_.split(",")).map(x => Row(x(0).toInt, x(1), x(2).toInt))

三.方法的使用

1.spark-shell 有的方法在程式碼要自己隱士磚換


df.select('name).show  這個在spark-shell 可以
或者df.select('name').show 
但是程式碼裡面不行,需要隱士轉

2.show原始碼


show原始碼  預設是true  顯示小於等於20條,對應行中的字元
是false就全部顯示出來
show(30,false)   也是全部顯示出來不會截斷
show(5)  但是後面的多與20字元就不會顯示
你可以show(5,false)

3.select方法原始碼

4.select 方法呼叫走的位置


df.select("name").show(false)
import spark.implicits._
//這樣不隱士轉換不行
df.select('name).show(false)
df.select($"name")
第一個select走的底層原始碼是 第一個原始碼圖
2,3個select走的原始碼是第二個

5.head原始碼


head 預設調第一條,你想展示幾條就調幾條

6.first() 展示第一條 底層呼叫的是head

7.sort原始碼


sort原始碼預設升序
降序解釋中有

四.sql的操作方法

1.官網臨時試圖

2.全域性試圖操作


全域性檢視加上  global_temp 規定

五.雜項

1.報錯

2.原因及程式碼


 val spark = SparkSession.builder()
   .appName("Test")
   .master("local[2]")
   .getOrCreate()
 val mess = spark.sparkContext.textFile("file:///D:\\test\\person.txt")
 import spark.implicits._
 val result = mess.map(_.split(",")).map(x => Info(x(0).toInt,x(1),x(2).toInt)).toDF()
 //在1.x 版本是可以的 在2.x不可以需要價格rdd
 result.map(x => x(0)).show() 
 這樣寫是對的
 result.rdd.map(x => x(0)).collect().foreach(println)
 去類中的資料兩種寫法:
 result.rdd.map(x => x(0)).collect().foreach(println)
result.rdd.map(x => x.getAs[Int]("id")).collect().foreach(println)

3.注意轉義字元


對於分隔符 |   你切分一定要加轉義字元,否則資料不對

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69941978/viewspace-2653388/,如需轉載,請註明出處,否則將追究法律責任。

相關文章