我在AWS Glue脚本中使用Spark SQL来转换S3中的某些数据。 这是脚本逻辑
数据格式CSV
编程语言:Python
1)使用Glue的Catalog从S3提取数据到Glue的DynamicDataFrame
2)使用toDF()从Glue的数据框中提取Spark数据框
3)制作Spark数据框Spark SQL表
createOrReplaceTempView()
4)使用SQL查询进行转换(这是我遇到问题的地方)
5)将最终数据帧转换为胶水动态数据帧
6)使用以下命令将最终数据帧存储到S3中
glueContext.write_dynamic_frame.from_options()
问题
当我在WHERE等SQL中使用比较时>
要么
(case when <some_columns> > <some int> then 1 else 0 end) as <some_newcol>
我遇到以下错误
pyspark.sql.utils.AnalysisException: u"cannot resolve '(sales.`cxvalue` >
100000)' due to data type mismatch: differing types in '(sales.`cxvalue` >
100000)' (struct<int:int,string:string> and int).; line 1 pos 35;\n'Project
['demand_amt]\n+- 'Filter (cxvalue#4 > 100000)\n +- SubqueryAlias sales\n +-
LogicalRDD [sales_id#0, customer_name#1, customer_loc#2, demand_amt#3L,
cxvalue#4]\n"
pyspark.sql.utils.AnalysisException: u"cannot resolve '(sales.`cxvalue` =
100000)' due to data type mismatch: differing types in '(sales.`cxvalue` =
100000)' (struct<int:int,string:string> and int).; line 1 pos 33;\n'Project
[customer_name#1, CASE WHEN (cxvalue#4 = 100000) THEN demand_amt#3 ELSE 0 END AS
small#12, CASE WHEN cxvalue#4 IN (200000,300000,400000) THEN demand_amt#3 ELSE 0
END AS medium#13]\n+- SubqueryAlias sales\n +- LogicalRDD [sales_id#0,
customer_name#1, customer_loc#2, demand_amt#3, cxvalue#4]\n"
这告诉我正在考虑将colums作为数字和字符串,这是特定于Spark而非AWS的。和() GROUP BY仅能很好地进行比较
我尝试了以下步骤
1)尝试使用Spark方法更改列类型-失败
df=df.withColumn(<column> df[<columns>].cast(DoubleType())) # df is Spark Data
111
胶水不允许更改spark数据框列类型的数据类型
2)如https://github.com/aws-samples/aws-gluesamples/中所述,使用了Glue的resoveChoice方法 blob / master / examples / resolve_choice.md。 resolveChoice方法有效-但sql失败,出现相同错误
3)在SQL查询中使用cast(<columns> as <data_type>)
–失败
4)在我的Google Cloud上启动Spark集群(仅确保与AWS无关)。仅使用具有上述相同逻辑的Spark –失败,并出现相同的错误
5)在相同的Spark集群和相同的数据集上,使用相同的逻辑,但使用StructType
和StructField
实施了强制模式
在创建新的Spark数据框时-已通过
这是示例数据
+--------+-------------+------------+----------+-------+
|sales_id|customer_name|customer_loc|demand_amt|cxvalue|
+--------+-------------+------------+----------+-------+
| 1| ABC| Denver CO| 1200| 300000|
| 2| BCD| Boston MA| 212| 120000|
| 3| CDE| Phoenix AZ| 332| 100000|
| 4| BCD| Boston MA| 211| 120000|
| 5| DEF| Portland OR| 2121|1000000|
| 6| CDE| Phoenix AZ| 32| 100000|
| 7| ABC| Denver CO| 3227| 300000|
| 8| DEF| Portland OR| 2121|1000000|
| 9| BCD| Boston MA| 21| 120000|
| 10| ABC| Denver CO| 1200|300000 |
+--------+-------------+------------+----------+-------+
这些是示例代码和查询失败的地方
sdf_sales.createOrReplaceTempView("sales")
tbl1="sales"
sql2="""select customer_name, (case when cxvalue < 100000 then 1 else 0) as small,
(case when cxvalue in (200000, 300000, 400000 ) then demand_amt else 0 end) as medium
from {0}
""".format(tbl1)
sql4="select demand_amt from {0} where cxvalue>100000".format(tbl1)
但是,这些查询与成功的Glue Job一起很好地工作
sql3="""select customer_name, sum(demand_amt) as total_spent from {0} GROUP BY customer_name""".format(tbl1)
挑战: 希望以某种方式允许我更改Spark Dataframe模式。任何建议将不胜感激。
答案 0 :(得分:0)
AWS Glue resolveChoice
解决了该问题。
编程逻辑错误:将Spark Frame视为可变的