概要
Databricks (Spark) にて dropduplicate や join にてエスケープ文字であるシングルクォートを指定した際のエラーへの対応方法を共有します。日本語のカラム(例:名前
)を Spark の SQL で扱う際にはシングルクォートを指定する必要があるのですが、 dropduplicate や join などを利用する際にシングルクォートを指定すると下記のようなエラーが発生します。
AnalysisException: Cannot resolve column name "
名前
" among (名前, 数値).
AnalysisException: [UNRESOLVED_USING_COLUMN_FOR_JOIN] USING column
名前
cannot be resolved on the left side of the join. The left-side columns: [名前
,数値
].
対応方法としては、dropduplicate や join を実行する際には、シングルクォートを TRIM する方法です。
col_list = ["`名前`"]
trimed_col_list = [col.lstrip("`").rstrip("`") for col in col_list]
df.dropDuplicates(trimed_col_list).display()
2024/06/04 時点にて、select
メソッドではエラーとならないがdropDuplicates
メソッドでエラーとなる原因を把握できておりませんが、自分のコードを見返した際に上記のような TRIM 処理を実施している理由を思い返せないため、備忘録として記事にします。Github Copilot から下記のような回答がでましたが、明確な理由を追えておりません。
Apache Sparkにおける
select
メソッドとdropDuplicates
メソッドの動作の違いにより、この現象が起こります。
select
メソッドでは、引数として与えられた文字列をそのままカラム名として解釈します。したがって、バッククオート(``)を含む文字列もカラム名として解釈されます。一方、
dropDuplicates
メソッドでは、引数として与えられた文字列をバッククオート()なしのカラム名として解釈します。したがって、バッククオート()を含む文字列を引数として与えると、該当するカラム名が見つからないためエラーが発生します。これらの違いは、PythonのPandasライブラリやSQLのようなデータ操作の抽象化を提供するApache Sparkの仕様に由来します。これらのメソッドは、様々なデータ操作の一部として設計されており、それぞれが異なるコンテキストで使用されるため、同じ引数が異なる解釈をされることがあります。
したがって、
dropDuplicates
メソッドを使用する際は、バッククオート(``)を含まないカラム名を引数として与えてください。
エラーの再現方法
事前準備
検証用のデータフレームを作成
schema = """
`名前` string,
`数値` int
"""
data = [
{
"名前": "あ",
"数値": 1,
},
{
"名前": "い",
"数値": 2,
},
{
"名前": "う",
"数値": 3,
},
]
df = spark.createDataFrame(data, schema)
select
メソッドの動作確認
df.select(["`名前`", "`数値`"]).display()
エラーの再現
dropDuplicates
メソッドのエラー
col_list = ["`名前`"]
df.dropDuplicates(col_list).display()
AnalysisException: Cannot resolve column name "
名前
" among (名前, 数値).
join
メソッドのエラー
col_list = ["`名前`"]
df.join(df, col_list, "INNER").display()
AnalysisException: [UNRESOLVED_USING_COLUMN_FOR_JOIN] USING column
名前
cannot be resolved on the left side of the join. The left-side columns: [名前
,数値
].
対応方法
dropDuplicates
メソッドのエラーへの対応方法
col_list = ["`名前`"]
trimed_col_list = [col.lstrip("`").rstrip("`") for col in col_list]
df.dropDuplicates(trimed_col_list).display()
join
メソッドのエラーへの対応方法
col_list = ["`名前`"]
trimed_col_list = [col.lstrip("`").rstrip("`") for col in col_list]
df.join(df, trimed_col_list, "INNER").display()