У меня есть фрейм данных, имеющий 3 столбца, два логических типа и один столбец в виде строки.
from pyspark.sql import SparkSession
from pyspark.sql.types import StructType, StructField, BooleanType, StringType
# Create a Spark session
spark = SparkSession.builder \
.appName("Condition Test") \
.getOrCreate()
# Sample data
data = [
(True, 'CA', None),
(True, 'US', None),
(False, 'CA', None)
]
# Define schema for the dataframe
schema = StructType([
StructField("is_flag", BooleanType(), nullable=False),
StructField("country", StringType(), nullable=False),
StructField("rule", BooleanType(), nullable=True)
])
# Create DataFrame
df = spark.createDataFrame(data, schema=schema)
# Show initial dataframe
df.show(truncate=False)
condition = (
(~col("is_flag")) |
((col("is_flag")) & (trim(col("country")) != 'CA') & nvl(col("rule"),lit(False)) != True)
)
df = df.filter(condition)
# show filtered dataframe
df.show(truncate=False)
Код выше возвращает данные ниже.
+-------+-------+----+
|is_flag|country|rule|
+-------+-------+----+
|true |CA |NULL|
|true |US |NULL|
|false |CA |NULL|
+-------+-------+----+
Однако, поскольку я прямо упоминаю ((col("is_flag")) & (trim(col("country")) != 'CA') & nvl(col("rule"),lit(False)) != True) т.е. Trim(col("country")) != 'CA', когда is_flag имеет значение true, я не ожидаю первой записи, мне нужны результаты, как показано ниже.
+-------+-------+----+
|is_flag|country|rule|
+-------+-------+----+
|true |US |NULL|
|false |CA |NULL|
+-------+-------+----+
Вопрос: почему приведенный выше код также возвращает первую запись |true |CA |NULL|, где, как мы явно упомянули, страна != 'CA', когда is_flag имеет значение true (логическое значение).
Однако то же самое, когда подтверждение применяется через sql, возвращает ожидаемый результат.
select *
from df
where (
not is_flag or
(is_flag and trim(country) != 'CA' and nvl(rule,False) != True)
)






Условие недействительно, поскольку оно не учитывает приоритет оператора и, следовательно, неверный результат. Оператор & имеет более высокий приоритет, чем !=.
Вот обновленное условие в скобках:
condition = (
(~col("is_flag")) |
((col("is_flag")) & (trim(col("country")) != 'CA') & (nvl(col("rule"),lit(False)) != True))
)
Выход:
+-------+-------+----+
|is_flag|country|rule|
+-------+-------+----+
|true |US |NULL|
|false |CA |NULL|
+-------+-------+----+
Вам не хватает скобок для
nvl() != True