我正在使用从JSON事件流转换而来的Dataframes处理事件,这些事件最终会像Parquet格式一样被写出来。
但是,一些JSON事件在键中包含空格,我想在将它转换为Parquet之前从数据框中记录和删除这些事件,因为,; {}()\ n \ t =被认为是特殊的Parquet架构(CatalystSchemaConverter)中的字符在 [1] 中列出,因此不应在列名中使用。
如何在Dataframe上对列名进行此类验证,并完全删除此类事件,而不会错误输出Spark Streaming作业。
[1] Spark的CatalystSchemaConverter
def checkFieldName(name: String): Unit = {
// ,;{}()\n\t= and space are special characters in Parquet schema
checkConversionRequirement(
!name.matches(".*[ ,;{}()\n\t=].*"),
s"""Attribute name "$name" contains invalid character(s) among " ,;{}()\\n\\t=".
|Please use alias to rename it.
""".stripMargin.split("\n").mkString(" ").trim)
}
答案 0 :(得分:2)
对于遇到此错误的pyspark用户,您可以使用此功能对列名进行规范化,然后再写入镶木地板文件:
import re
# invalid characters in parquet column names are replaced by _
def canonical(x): return re.sub("[ ,;{}()\n\t=]+", '_', x.lower())
renamed_cols = [canonical(c) for c in df.columns]
df = df.toDF(*renamed_cols)
如果您也想从列名中删除重音符号,则可以使用:
import unicodedata
# strips accents from string value
def strip_accent(x): return unicodedata.normalize('NFKD', x).encode('ASCII', 'ignore').decode()
放在一起:
renamed_cols = [strip_accent(canonical(c)) for c in df.columns]
df = df.toDF(*renamed_cols)
答案 1 :(得分:1)
对于包含空格的列名,我也遇到了同样的问题。
解决方案的第一部分是将名称放在反引号中。
解决方案的第二部分是用下划线替换空格。
对不起,但是我只准备好了pyspark代码:
from pyspark.sql import functions as F
df_tmp.select(*(F.col("`" + c+ "`").alias(c.replace(' ', '_')) for c in df_tmp.columns)
答案 2 :(得分:1)
这是我使用Regex的解决方案,以便按照实木复合地板约定重命名数据框的所有列:
df.columns.foldLeft(df){
case (currentDf, oldColumnName) => currentDf.withColumnRenamed(oldColumnName, oldColumnName.replaceAll("[ ,;{}()\n\t=]", ""))
}
我希望对您有帮助,
答案 3 :(得分:0)
使用alias
更改字段名称,而不使用这些特殊字符。
答案 4 :(得分:0)
尝试使用正则表达式替换坏符号。检查我的answer。
答案 5 :(得分:0)
对于在pyspark中遇到此问题的每个人:重命名列后,这甚至都发生在我身上。在一些迭代之后,我可以使它工作的一种方法是:
file = "/opt/myfile.parquet"
df = spark.read.parquet(file)
for c in df.columns:
df = df.withColumnRenamed(c, c.replace(" ", ""))
df = spark.read.schema(df.schema).parquet(file)