我有一个数据框yeadDF,它是通过读取RDBMS表创建的,如下所示:
val yearDF = spark.read.format("jdbc").option("url", connectionUrl)
.option("dbtable", s"(${query}) as year2017")
.option("user", devUserName)
.option("password", devPassword)
.option("numPartitions",15)
.load()
在将其导入HDFS的Hive表之前,我必须对上述数据框应用正则表达式模式。下面是正则表达式模式:
regexp_replace(regexp_replace(regexp_replace(regexp_replace(regexp_replace(%s, E'[\\\\n]+', ' ', 'g' ), E'[\\\\r]+', ' ', 'g' ), E'[\\\\t]+', ' ', 'g' ), E'[\\\\cA]+', ' ', 'g' ), E'[\\\\ca]+', ' ', 'g' )
我应该仅在数据帧yearDF
中数据类型为String的列上应用此正则表达式。我尝试了以下方法:
val regExpr = yearDF.schema.fields
.map(x =>
if(x.dataType == String)
"regexp_replace(regexp_replace(regexp_replace(regexp_replace(regexp_replace(%s, E'[\\\\n]+', ' ', 'g' ), E'[\\\\r]+', ' ', 'g' ), E'[\\\\t]+', ' ', 'g' ), E'[\\\\cA]+', ' ', 'g' ), E'[\\\\ca]+', ' ', 'g' ) as %s".format(x,x)
)
yearDF.selectExpr(regExpr:_*)
但是它给了我一个编译错误:Type mismatch, expected: Seq[String], actual: Array[Any]
我不能使用yearDF.columns.map
,因为这将作用于所有列,并且
我无法在这里正确地形成逻辑。
谁能让我知道如何在数据框yearDF
上仅将上述正则表达式应用于String类型的列吗?
答案 0 :(得分:1)
这是因为yearDF.selectExpr(regExpr:_*)
期望regExpr
是String的Seq,而regExpr是Array [Any]。好的,您在消息中看到的。但是为什么是Array [Any]?
查看地图功能。对于架构中的每个字段,您正在映射: -每个具有StringType的列都将包含正则表达式 -其他情况->无。
顺便说一句,请使用org.apache.spark.sql.types.StringType
,String
。
因此,改为:
val regExpr = yearDF.schema.fields
.map(x =>
if (x.dataType == StringType)
"regexp_replace(regexp_replace(regexp_replace(regexp_replace(regexp_replace(%s, E'[\\\\n]+', ' ', 'g' ), E'[\\\\r]+', ' ', 'g' ), E'[\\\\t]+', ' ', 'g' ), E'[\\\\cA]+', ' ', 'g' ), E'[\\\\ca]+', ' ', 'g' ) as %s".format(x.name, x.name)
else x.name
)
yearDF.selectExpr(regExpr:_*)
答案 1 :(得分:0)
在将regex_replace()仅应用于数据帧的字符串列时,我也遇到了类似的问题。 诀窍是制作regEx模式(在我的情况下为“模式”),该模式可在双引号内进行解析并应用转义字符。
val pattern="\"\\\\\\\\[\\\\\\\\x{FFFD}\\\\\\\\x{0}\\\\\\\\x{1F}\\\\\\\\x{81}\\\\\\\\x{8D}\\\\\\\\x{8F}\\\\\\\\x{90}\\\\\\\\x{9D}\\\\\\\\x{A0}\\\\\\\\x{0380}\\\\\\\\]\""
val regExpr = parq_out_df_temp.schema.fields.map(x =>
if(x.dataType == StringType){s"regexp_replace(%s, $pattern,'') as %s".format(x.name,x.name)}
else x.name)
val parq_out=parq_out_df_temp.selectExpr(regExpr:_*)
这对我来说很好!