Apache spark 将输入值拆分为Pyspark数据帧中的不同字段
我正在使用Pyspark dataframe处理日志文件。下面是我使用spark.read.text从文件中读取的示例日志Apache spark 将输入值拆分为Pyspark数据帧中的不同字段,apache-spark,pyspark,apache-spark-sql,pyspark-dataframes,Apache Spark,Pyspark,Apache Spark Sql,Pyspark Dataframes,我正在使用Pyspark dataframe处理日志文件。下面是我使用spark.read.text从文件中读取的示例日志 [Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] client denied by server configuration: /export/home/htdocs/test [Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] client denied b
[Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] client denied by server configuration: /export/home/htdocs/test
[Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] client denied by server configuration: /export/home/htdocs/test
我想把这个日志分成5个字段,即时间戳、信息、URL、消息、路径
如何像那样分开?
请帮我解决这个问题。非常感谢 所以你有两个选择 分隔符 因此,您的日志文件有一些明显的分隔符,您可以根据这些分隔符进行拆分。为此,请使用
split
功能
从pyspark.sql导入函数为F
df=df.withColumn(
“拆分_列”,
F.split(F.col(“日志列”),分隔符)
)
#“split_column”现在是一个数组,所以我们需要从数组中取出项目
df=df.withColumn(
“时间戳”,
F.col(“拆分列”).getItem(0)
)
由于有两个不同的字段,因此需要将多个拆分与修剪组合起来
大概
#在方括号中拆分
df=df.withColumn(
“拆分括号和列”,
F.split(F.col(“对数列”),“]”)
)
df=df.withColumn(
“时间戳”,
F.col(“拆分括号列”).getItem(0).trim()
)
df=df.withColumn(
“信息”,
F.col(“拆分括号列”).getItem(1).trim()
)
df=df.withColumn(
“网址”,
F.col(“拆分支架柱”).getItem(2).trim()
)
df=df.withColumn(
“剩余”,
F.col(“拆分支架柱”).getItem(3).trim()
)
#在冒号上拆分剩余的“:”
df=df.withColumn(
“拆分冒号列”,
F.分割(F.col(“剩余”),“:”)
)
df=df.withColumn(
“消息”,
F.col(“拆分冒号列”).getItem(0.trim()
)
df=df.withColumn(
“路径”,
F.col(“拆分冒号列”).getItem(1).trim()
)
#清理临时列
df.下降(“分体式支架柱”)
df.下降(“剩余”)
df.drop(“拆分冒号列”)
正则表达式
由于格式非常固定,您可以使用正则表达式执行相同的操作
重新导入
正则表达式模式=r“\[()\]\[()\]\[()\]\[()\]()\:()”
匹配组=[“时间戳”、“信息”、“URL”、“消息”、“路径”]
对于范围内的i(重新编译(regex_模式).groups):
df=df.withColumn(
匹配组[i],
F.regexp_extract(F.col(log_列),regex_模式,i+1),
)
其中,log\u column
是Spark数据框中包含日志消息的列
注意:检查regex\u模式
,因为我前面没有编辑器。所以您有两个选项
val sUDF = udf((s: String) => {
val s2 = s.split("]").map(_.replace("[", "").trim).reverse
s2.tail.reverse ++ s2.head.split(": ")
})
val sDF = Seq("[Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] client denied by server configuration: /export/home/htdocs/test")
.toDF("log")
.withColumn("arr", sUDF('log))
.select(
'arr(0).alias("Timestamp"),
'arr(1).alias("Info"),
'arr(2).alias("URL"),
'arr(3).alias("Message"),
'arr(4).alias("Path")
)
sDF.show(false)
// +------------------------+-----+----------------+-------------------------------------+------------------------+
// |Timestamp |Info |URL |Message |Path |
// +------------------------+-----+----------------+-------------------------------------+------------------------+
// |Wed Oct 11 14:32:52 2000|error|client 127.0.0.1|client denied by server configuration|/export/home/htdocs/test|
// +------------------------+-----+----------------+-------------------------------------+------------------------+
分隔符
因此,您的日志文件有一些明显的分隔符,您可以根据这些分隔符进行拆分。为此,请使用split
功能
从pyspark.sql导入函数为F
df=df.withColumn(
“拆分_列”,
F.split(F.col(“日志列”),分隔符)
)
#“split_column”现在是一个数组,所以我们需要从数组中取出项目
df=df.withColumn(
“时间戳”,
F.col(“拆分列”).getItem(0)
)
由于有两个不同的字段,因此需要将多个拆分与修剪组合起来
大概
#在方括号中拆分
df=df.withColumn(
“拆分括号和列”,
F.split(F.col(“对数列”),“]”)
)
df=df.withColumn(
“时间戳”,
F.col(“拆分括号列”).getItem(0).trim()
)
df=df.withColumn(
“信息”,
F.col(“拆分括号列”).getItem(1).trim()
)
df=df.withColumn(
“网址”,
F.col(“拆分支架柱”).getItem(2).trim()
)
df=df.withColumn(
“剩余”,
F.col(“拆分支架柱”).getItem(3).trim()
)
#在冒号上拆分剩余的“:”
df=df.withColumn(
“拆分冒号列”,
F.分割(F.col(“剩余”),“:”)
)
df=df.withColumn(
“消息”,
F.col(“拆分冒号列”).getItem(0.trim()
)
df=df.withColumn(
“路径”,
F.col(“拆分冒号列”).getItem(1).trim()
)
#清理临时列
df.下降(“分体式支架柱”)
df.下降(“剩余”)
df.drop(“拆分冒号列”)
正则表达式
由于格式非常固定,您可以使用正则表达式执行相同的操作
重新导入
正则表达式模式=r“\[()\]\[()\]\[()\]\[()\]()\:()”
匹配组=[“时间戳”、“信息”、“URL”、“消息”、“路径”]
对于范围内的i(重新编译(regex_模式).groups):
df=df.withColumn(
匹配组[i],
F.regexp_extract(F.col(log_列),regex_模式,i+1),
)
其中,log\u column
是Spark数据框中包含日志消息的列
注意:检查regex\u模式
,因为我前面没有编辑器。非常感谢!如果可能的话,你能用Python编写这段代码吗?请注意,在Python中使用UDF要比使用内置程序慢得多——如果日志很小,你可能会关心这一点,但如果你谈论的是MBs文件,这将是相当可观的。感谢Morgan,我将对此进行研究!谢谢!如果可能的话,你能用Python编写这段代码吗?请注意,在Python中使用UDF要比使用内置程序慢得多——如果日志很小,你可能会关心这一点,但如果你谈论的是MBs文件,这将是相当可观的。感谢Morgan,我将对此进行研究!谢谢!在delimiter方法中,我可以使用什么作为上述日志代码的分隔符?同样在正则表达式方法中,我在“F.regexp_extract(F.col(column),regex_pattern,I+1)”中得到列未定义错误。我是否应该用match_groups[I]替换列?对于分隔符代码,您可以在第一次传递时使用]
作为分隔符。然后我会在第二遍中使用:
。对于正则表达式,您需要将列
替换为Spark数据框中调用的日志消息-很抱歉,我假设您的数据已经在数据框中。非常感谢!请您在代码中更改此项,以便我接受您的解决方案作为正确答案谢谢!在delimiter方法中,我可以使用什么作为上述日志代码的分隔符?同样在regex方法中,我在“F.regexp_extract(F.col(column),regex_pattern,I+1)”中得到了列未定义错误
val sUDF = udf((s: String) => {
val s2 = s.split("]").map(_.replace("[", "").trim).reverse
s2.tail.reverse ++ s2.head.split(": ")
})
val sDF = Seq("[Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] client denied by server configuration: /export/home/htdocs/test")
.toDF("log")
.withColumn("arr", sUDF('log))
.select(
'arr(0).alias("Timestamp"),
'arr(1).alias("Info"),
'arr(2).alias("URL"),
'arr(3).alias("Message"),
'arr(4).alias("Path")
)
sDF.show(false)
// +------------------------+-----+----------------+-------------------------------------+------------------------+
// |Timestamp |Info |URL |Message |Path |
// +------------------------+-----+----------------+-------------------------------------+------------------------+
// |Wed Oct 11 14:32:52 2000|error|client 127.0.0.1|client denied by server configuration|/export/home/htdocs/test|
// +------------------------+-----+----------------+-------------------------------------+------------------------+