How to pass array to pyspark lit function?
在本範例你會學到:
- 如何使用 lit 函式
- 將 array 傳給 lit
- 解決以下問題
py4j.protocol.Py4JJavaError: An error occurred while calling z:org.apache.spark.sql.functions.lit.: java.lang.RuntimeException: Unsupported literal type class java.util.ArrayList
在本範例你需要先準備好:
- 本範例部份function 可能只適用於
spark 版本 >= 2.4
以下目的是為了展示 lit 使用方式,其範例看起來可能有點傻,請見諒
1.如何使用 lit
由於 spark 在操作的時候都是以 rdd
或是 dataframe
的形式在使用,若不是這兩個形態是不能互相處理任何事情的,例如:
- 若我想要新增一個數值在 dataframe 上,而且每個值都一樣,可以這麼做
from pyspark import SparkConf, SparkContext
from pyspark.sql import SparkSession
import pyspark.sql.functions as F
from pyspark.sql.types import *
spark = SparkSession.builder.appName('lit_example').getOrCreate()
# Create dataframe
df = spark.createDataFrame([(1, 2, 3, 4, 5, 6),(12, 24, 33, 44, 54, 66)], ["A", "B", "C", "D", "E", "F"])
# 不能直接給值會報錯
# 會有以下錯誤: AssertionError: col should be Column
df_lit = df.withColumn('lit_column',2)
# 正確寫法
df_lit = df.withColumn('lit_column',F.lit(2))
df_lit.show()
2.lit 與 array 的使用方式
- 當我想要新增一個 array 的時候,就會遇到上方的錯誤訊息
Unsupported literal type class java.util.ArrayList
。延續上方的例子:
# Create dataframe
df = spark.createDataFrame([(1, 2, 3, 4, 5, 6),(12, 24, 33, 44, 54, 66)], ["A", "B", "C", "D", "E", "F"])
# 假設我要傳入這個list
input_list = [2,4,6,8]
# 不能直接給list會報錯
df_lit = df.withColumn('lit_column',F.lit(input_list))
# 正確寫法
df_lit = df.withColumn('lit_column',F.array([F.lit(x) for x in input_list]))
df_lit.show()
原理其實就是告知 dataframe 我要放入的資料是 F.array
型態,然後把資料裡所有的值都用 for loop 進行 lit 轉換成 dataframe 理解的型態就可使用 F.array([F.lit(x) for x in input_list])
。
相關參考
就如前言所說,此範例傻傻的,其實也可以用 udf
解決,有興趣的可參考資料。
https://stackoverflow.com/questions/49683897/passing-array-to-python-spark-lit-function