1. 程式人生 > 實用技巧 >Spark權威指南讀書筆記(三) 處理不同的資料型別

Spark權威指南讀書筆記(三) 處理不同的資料型別

Spark權威指南讀書筆記(三) 處理不同的資料型別

一、轉換成Spark型別

使用lit函式將原始型別轉換為Spark型別

二、處理布林型別

布林語句由四個要素組成: and、or、true和false。

scala中有一些關於 == 和 ===用法的特殊語義。在Spark中,如果想通過相等條件來進行過濾,應該使用 ===(等於) 或 =!=(不等於)符號,還可以使用not函式和equalTo方法實現。

另一種方法是使用字串形式的謂詞表達式

對於鏈式連線的方式, Spark會將所有過濾條件合併為一條語句,並同時執行這些過濾器,建立and語句。

構建過濾列

注:建立布林表示式時,需注意空值處理否則易出現問題。可使用以下語句保證執行空值執行的等價測試。

三、處理數值型別

1.基礎運算

2.四捨五入

使用round或bround函式進行四捨五入,round/bround支援某個精度級別的轉換, 若恰好處於兩數之間,則round函式會向上取整, bround函式向下取整。

3.計算兩列相關性(以Pearson係數為例)
$$
\rho = \frac{cov(X, Y)}{\sigma x \sigma y} = \frac{E[(X-\mu x)(Y - \mu y)]}{\sigma x \sigma y} \\
r = \frac{\sum_{i = 1}^{n} (X_i - \bar X)(Y_i - \bar(Y) }{\sqrt[]{\sum_{i = 1}^n (X_i - \bar X)^2} \sqrt[]{\sum_{i = 1}^n (Y_i - \bar Y)^2}} \\
r = \frac{1}{n-1} \sum_ {i = 1} ^ n
$$

  • 當 r > 0時, 表示兩個變數正相關,即一個變數值越大則另一個變數也會越大
  • 當 r < 0時, 表示兩個變數負相關, 即一個變數值越大則另一個變數值反而越小
  • 當 r = 0時, 表示兩個變數不是線性相關
  • 當 r = 1 或 r = -1時, 意味著兩個變數X和Y適合用直線方程描述

4.計算一列或一組列的彙總統計資訊

使用describe方法,可以計算所有數值型別列的計數、平均值、標準差、最小值和最大值(更精確統計函式使用StatFunctions包)

5.行ID

使用monotonically_increasing_id函式為每行新增一個唯一的ID,它會從0開始,為每行生成一個唯一值。

四、處理字串型別

1.大小寫

使用initcap函式將會給定字串中空格分隔的每個單詞首字母大寫,使用upper或lower將字串轉為大寫或小寫

2.處理字串周圍的空格

注:如果lpad或rpad輸入數值引數小於字串長度,它將從字串右側刪除字元。

五、正則表示式

1.regexp_replace替換值

2.regexp_extract提取值

3.使用translate函式實現字元替換工作

這是在字元級上完成的操作,並將用給定字串替換掉所有出現的某字串。

4.使用contains檢查是否存在, 返回布林值

使用不定量引數解決問題

六、處理日期和時間戳型別

Spark內部有日曆日期的data, 及包括日期和時間資訊的timestamp。Spark會盡最大努力正確識別列資料型別。當設定inferSchema為true時,Spark會自動推理出日期與時間戳資料型別。

注:在2.1版本及之前,如果時區沒有被顯示指定,Spark會根據計算機時區進行解析。如果有必要的情況下,可以通過設定spark.conf.sessionLocalTimeZone設定會話本地時區,根據java的TimeZone格式設定。

Spark的TimestampType類只支援二級精度,這意味著如果處理毫秒或微秒,可能需要將資料作為Long型操作才能解決問題。再強制轉換為TimeStampType時, 任何更高精度都被刪除。

1.使用current_date current_timestamp獲取當前日期和當前時間

2.date_add date_sub增減天數

3.使用datediff返回兩個日期之間的天數, months_between返回兩個日期之間的月數

4.to_date 使用指定格式將字串轉換為日期資料

須使用java_simpleDateFrame指定想要的格式。如果Spark無法解析日期,其不會丟擲錯誤,而只是返回null。

解決此類問題,需要根據Java SimpleDataFormat標準指定日期格式。

to_date選擇指定一種日期格式, to_timestamp強制要求使用一種日期格式

注:面對可能需要處理null值或不同時區及格式的日期時,建議使用顯示型別轉換,切勿使用隱式型別轉換。

七、空值處理

在實際應用中,建議始終使用null來表示DF缺少或空的資料。使用null值有利於Spark進行優化。基於DataFrame, 處理null值主要使用.na子包。

注:對於Spark而言,顯式處理空值比隱式處理較好。當宣告列沒有空值時,這並不是實際意義上的強制無空值,當定義一個數據模式時,其中所有的列被宣告為不具有null值型別時,Spark不會強制拒絕空值插入。空值設定本身只是為了幫助Spark SQL處理該列時進行優化。

1.合併

使用coalesce函式,實現從一組列中選擇第一個非空值,即第一個空值

2.ifnull、nullif、nvl、nvl2等SQL函式

ifnull =》如果第一個值為空,則選擇第二個值,並將其預設為第一個。

nullif =》 如果兩個值相等,則返回null, 否則返回第二個值

nvl =》 若第一個值為null, 則返回第二個值,否則返回第一個值

nvl2 =》 若第一個值不為null, 返回第二個值, 否則他將返回第一個值

3.drop

使用drop刪除包含null的行,預設刪除包含null值的行。若指定“any”作為引數,當存在一個值為null時,即刪除該行;若指定“all”為引數, 只有當所有的值為null或者NaN才能刪除該行。也可以通過指定某幾列,來對列進行刪除空值操作。

df.na.drop()
df.na.drop("any")
df.na.drop("all")
df.na.drop("all", Seq("StockCode", "InvoiceNo"))

4.fill

fill函式可以使用一組值填充一列或多列,它可以通過指定一個對映(即一個特定值和一組列)來完成。

df.na.fill("All Null values become this string")

//需要注意列的型別
df.na.fill(5, Seq("StockCode", "InvoiceNo"))

//使用對映實現
val fillColValues = Map("StockCode" -> 5, "Description" -> "No Value")
df.na.fill(fillColValue)

5.replace

根據當前值替換掉 某列中所有值,唯一要求時替換值與原始值的型別相同。

df.na.replace("Description", Map("" -> "UNKNOWN"))

八、複雜型別

1.結構體

結構體可以使用“.”訪問列或使用getField方法,還可以使用*查詢結構體中的所有值。

2.陣列

split函式並指定分隔符執行操作

求陣列長度

array_contains 查詢陣列是否包含某個值

explode

explode函式輸入引數為一個包含陣列的列,併為該陣列的每個值建立一行

map

map對映是通過map函式構建兩列內容鍵值對對映形式。

九、JSON型別

十、使用者自定義函式

UDF,即使用者自定義函式可以使使用者使用python或scala編寫自己的自定義轉換操作,甚至使用外部庫。UDF可以將一個或多個列作為輸入,同時也可以返回一個或多個列。預設情況下,這些函式被註冊為SparkSession或者Context的臨時函式。