这是我的实现
from pyspark.sql import functions as F
from pyspark.sql.types import *
df = spark.createDataFrame(
[
("001", "John", "John", "123", "123"),
("002", "Sara", "Sarah", "234", "234"),
("003", "Bill", "William", "999", "111"),
("004", "Lisa", "Lisa", "888", "333"),
("005", "Martin", "Martin", "345", "345"),
("006", "Margaret", "Margaret", "456", "456"),
("007", "Oscar", "Oscar", "678", "678"),
("008", "Peter", "Peter", "789", "789"),
],
["ID", "Name1", "Name2", "Zip1", "Zip2"],
)
#df.show()
rule_df = spark.createDataFrame(
[
("R001", "Name1", "Name2", "EQUALS"),
("R002", "Zip1", "Zip2", "EQUALS"),
],
["ID", "FieldLeft", "FieldRight", "ComparisonOperation"],
)
#rule_df.show()
final_rule_df = (rule_df
.withColumn(
"operator",
F.when(
F.lower(F.col("ComparisonOperation")) == "equals",
F.lit(" == "),
)
.when(
F.lower(F.col("ComparisonOperation")) == "not equals",
F.lit(" != "),
)
.when(
F.lower(F.col("ComparisonOperation")) == "greater than",
F.lit(" > "),
)
.when(
F.lower(F.col("ComparisonOperation")) == "less than",
F.lit(" < "),
)
.otherwise(F.lit("operator_na")),
)
.filter(F.col("operator") != "operator_na" )
.withColumn("expression", concat(F.col("FieldLeft"),F.col("operator"), F.col("FieldRight")) )
.drop("operator")
#.withColumn(
# "select_clause",
# F.concat(
# F.lit('"'),
# F.lit( F.col("FieldLeft") ),
# F.lit(" as " + F.col("FieldLeft")._jc.toString()),
# F.lit('"'),
# F.lit(", "),
# F.lit('"'),
# F.col("FieldRight"),
# F.lit(" as " + F.col("FieldRight")._jc.toString()),
# F.lit('"'),
# )
#)
)
final_rule_df.show(truncate=False)
schema = StructType(
[
StructField("Rule", StringType(), True),
StructField("ID", StringType(), True),
StructField("FieldLeft", StringType(), True),
StructField("FieldRight", StringType(), True),
]
)
final_non_compliant_df = spark.createDataFrame(
spark.sparkContext.emptyRDD(), schema
)
rule_df_rows = final_rule_df.select("*").collect()
for row in rule_df_rows:
rule_id = row.ID
print(f"rule_id: {rule_id}")
expression = row.expression
print(f"expression: {expression}")
#select_clause = row.select_clause
#print(f"select_clause: {select_clause}")
rule_df = df.filter(expr(expression))
#rule_df.show()
non_compliant_df = (df.subtract(rule_df)
.withColumn("Rule", F.lit(rule_id))
.withColumn("FieldLeft", F.col(row.FieldLeft))
.withColumn("FieldRight", F.col(row.FieldRight))
.selectExpr("Rule", "ID", "FieldLeft", "FieldRight")
)
non_compliant_df.show()
final_non_compliant_df = final_non_compliant_df.union(non_compliant_df)
final_non_compliant_df.show()
输出:
+----+---------+----------+-------------------+--------------+
|ID |FieldLeft|FieldRight|ComparisonOperation|expression |
+----+---------+----------+-------------------+--------------+
|R001|Name1 |Name2 |EQUALS |Name1 == Name2|
|R002|Zip1 |Zip2 |EQUALS |Zip1 == Zip2 |
+----+---------+----------+-------------------+--------------+
rule_id: R001
expression: Name1 == Name2
+----+---+---------+----------+
|Rule| ID|FieldLeft|FieldRight|
+----+---+---------+----------+
|R001|003| Bill| William|
|R001|002| Sara| Sarah|
+----+---+---------+----------+
rule_id: R002
expression: Zip1 == Zip2
+----+---+---------+----------+
|Rule| ID|FieldLeft|FieldRight|
+----+---+---------+----------+
|R002|004| 888| 333|
|R002|003| 999| 111|
+----+---+---------+----------+
最终输出:
+----+---+---------+----------+
|Rule| ID|FieldLeft|FieldRight|
+----+---+---------+----------+
|R001|003| Bill| William|
|R001|002| Sara| Sarah|
|R002|004| 888| 333|
|R002|003| 999| 111|
+----+---+---------+----------+