Apache spark Spark Dataframe验证拼花写入的列名

Apache spark Spark Dataframe验证拼花写入的列名,apache-spark,pyspark,apache-spark-sql,spark-streaming,parquet,Apache Spark,Pyspark,Apache Spark Sql,Spark Streaming,Parquet,我正在使用从JSON事件流转换而来的数据帧处理事件,这些事件最终被写成拼花格式 但是,一些JSON事件在键中包含空格,我希望在将其转换为拼花之前记录并过滤/删除数据帧中的此类事件,因为;{}()\n\t=被认为是拼花地板模式(CatalystSchemaConverter)中的特殊字符,如下面的[1]所列,因此不允许在列名中使用 如何在Dataframe中对列名执行此类验证,并完全删除此类事件,而不会导致Spark流作业出错 [1] 火花催化转换器 def checkFieldName(名称:字

我正在使用从JSON事件流转换而来的数据帧处理事件,这些事件最终被写成拼花格式

但是,一些JSON事件在键中包含空格,我希望在将其转换为拼花之前记录并过滤/删除数据帧中的此类事件,因为
;{}()\n\t=
被认为是拼花地板模式(CatalystSchemaConverter)中的特殊字符,如下面的[1]所列,因此不允许在列名中使用

如何在Dataframe中对列名执行此类验证,并完全删除此类事件,而不会导致Spark流作业出错

[1] 火花催化转换器

def checkFieldName(名称:字符串):单位={
//,;{}()\n\t=和空格是拼花地板架构中的特殊字符
检查转换要求(
!name.matches(“.[,;{}()\n\t=].*),
属性名“$name”包含“,;{}()\\n\\t=”中的无效字符。
|请使用别名重命名它。
.stripMargin.split(“\n”).mkString(”).trim
)
}

使用
别名
更改字段名,但不使用那些特殊字符。

我对包含空格的列名也有同样的问题。
解决方案的第一部分是将名称放在反引号中。
解决方案的第二部分是用下划线替换空格

抱歉,我只准备了pyspark代码:

from pyspark.sql import functions as F

df_tmp.select(*(F.col("`" + c+ "`").alias(c.replace(' ', '_')) for c in df_tmp.columns)

对于在pyspark中体验到这一点的每个人:这甚至发生在我重命名专栏之后。我可以在一些迭代之后使其工作的一种方法是:

file=“/opt/myfile.parquet”
df=spark.read.parquet(文件)
对于df.columns中的c:
df=df.withColumnRename(c,c.replace(“,”))
df=spark.read.schema(df.schema).parquet(文件)

在写入拼花地板之前,可以使用正则表达式将所有无效字符替换为下划线。此外,还可以从列名中去掉重音符号

这里有一个函数
normalize
,它可以为Scala和Python实现这一点:

斯卡拉
/**
*通过用下划线替换无效字符来规范列名
*并去除口音
*
*@param columns数据框列名列表
*@返回规范化列名列表
*/
def规格化(列:Seq[String]):Seq[String]={
columns.map{c=>
org.apache.commons.lang3.StringUtils.stripAccents(c.replaceAll(“[,;{}()\n\t=]+”,“”))
}
}
//使用函数
val df2=df.toDF(规范化(df.columns):\uU4*)
python
导入Unicode数据
进口稀土
def规格化(列:str)->str:
"""
通过用下划线替换无效字符来规范列名
去掉重音并使其小写
:param column:列名
:return:规范化列名
"""
n=re.sub(r“[,;{}()\n\t=]+”,“"”,column.lower())
返回unicodedata.normalize('NFKD',n).encode('ASCII','ignore').decode()
#使用函数
df=df.toDF(*映射(规范化,df.columns))

这是我的解决方案,使用正则表达式按照拼花地板约定重命名所有数据框的列:

df.columns.foldLeft(df){
大小写(currentDf,oldColumnName)=>currentDf.WithColumnRename(oldColumnName,oldColumnName.replaceAll(“[,;{}()\n\t=],”))
}

我希望这会有所帮助,

您可以用正则表达式替换坏符号。检查我的,妈的!它起作用了!我认为这应该是一个错误,重命名根本不起作用。这在scala中不起作用:错误:值列不是数组的成员[org.apache.spark.sql.Row]这对我有效,但列的内容为null。。。。这对col名称有效,但现在内容都是nan!!太棒了,谢谢