我有一个通过读取RDBMS表创建的数据框,如下所示:
val dataDF = 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表中之前,我们被要求在String数据类型的数据帧的列上应用regex_replace模式。这就是我的应用方式:
val regExpr = dataDF.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
}
dataDF.selectExpr(regExpr:_*)
但是当我执行代码时,它以以下异常结尾:
Exception in thread "main" org.apache.spark.sql.catalyst.parser.ParseException:
Literals of type 'E' are currently not supported.(line 1, pos 88)
== SQL ==
regexp_replace(regexp_replace(regexp_replace(regexp_replace(regexp_replace(period_name, E'[\\n]+', ' ', 'g' ), E'[\\r]+', ' ', 'g' ), E'[\\t]+', ' ', 'g' ), E'[\\cA]+', ' ', 'g' ), E'[\\ca]+', ' ', 'g' ) as period_name
----------------------------------------------------------------------------------------^^^
我使用以下命令打印了模式:println(dataDF.schema)。该代码正确识别了String列,您可以在其中看到列名称:period_name
Schema: StructType(StructField(forecast_id,LongType,true), StructField(period_num,DecimalType(15,0),true), StructField(period_name,StringType,true), StructField(drm_org,StringType,true), StructField(ledger_id,LongType,true), StructField(currency_code,StringType,true))
要求是删除多种格式的空格。 “字符串”列中的数据可以包含带有多种格式的空格的值。
1, b,c, d,
e,Ωåf
存在多个空格,制表符空间,换行符之后出现的值,如果有的话删除特殊字符等, 上一行应转换为:1,b,c,d,e,f
读取的表存在于postgres数据库中。我试图理解为什么E导致异常,但是我没有头绪。谁能让我知道如何解决此异常?
答案 0 :(得分:1)
出于测试目的,我创建了一个数据框,其中在 col3 列中使用提供的带有特殊字符的字符串作为
+----+----+--------------------------------------------------------------------+
|col1|col2|col3 |
+----+----+--------------------------------------------------------------------+
|a |1 |1, - b,c, d,
|
|e,Ωåf|
+----+----+--------------------------------------------------------------------+
然后按照注释中的建议使用选择带字符串类型的列和使用foldleft和withColumn 和使用regexp_replace
在withColumn 中,您可以执行以下
//getting column names which are string type
val stringColumns = df.schema.fields.filter(_.dataType == StringType).map(_.name)
//applying regex to replace all characters except digits, characters (a to z and A to Z) and commas
import org.apache.spark.sql.functions._
val finaldf = stringColumns.foldLeft(df){(tempdf, colName) => tempdf.withColumn(colName, regexp_replace(col(colName), "[ ](?=[ ])|[^,A-Za-z0-9]+", ""))}
因此finaldf
将与
+----+----+-----------+
|col1|col2|col3 |
+----+----+-----------+
|a |1 |1,b,c,d,e,f|
+----+----+-----------+
您可以根据需要更改 regex模式 [ ](?=[ ])|[^,A-Za-z0-9]+
。目前,A-Za-z0-9
个字符仅未删除
我希望答案会有所帮助