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的臨時函式。