web-dev-qa-db-fra.com

Opérateur de comparaison dans PySpark (pas égal /! =)

J'essaie d'obtenir toutes les lignes dans une trame de données où deux drapeaux sont définis sur "1" et par la suite tous ceux où un seul des deux est défini sur "1" et l'autre PAS ÉGAL à "1 "

Avec le schéma suivant (trois colonnes),

df = sqlContext.createDataFrame([('a',1,'null'),('b',1,1),('c',1,'null'),('d','null',1),('e',1,1)], #,('f',1,'NaN'),('g','bla',1)],
                            schema=('id', 'foo', 'bar')
                            )

J'obtiens le dataframe suivant:

+---+----+----+
| id| foo| bar|
+---+----+----+
|  a|   1|null|
|  b|   1|   1|
|  c|   1|null|
|  d|null|   1|
|  e|   1|   1|
+---+----+----+

Lorsque j'applique les filtres souhaités, le premier filtre (foo = 1 AND bar = 1) fonctionne, mais pas l'autre (foo = 1 AND NOT bar = 1)

foobar_df = df.filter( (df.foo==1) & (df.bar==1) )

rendements:

+---+---+---+
| id|foo|bar|
+---+---+---+
|  b|  1|  1|
|  e|  1|  1|
+---+---+---+

Voici le filtre sans comportement:

foo_df = df.filter( (df.foo==1) & (df.bar!=1) )
foo_df.show()
+---+---+---+
| id|foo|bar|
+---+---+---+
+---+---+---+

Pourquoi ne filtre-t-il pas? Comment puis-je obtenir les colonnes où seul foo est égal à "1"?

11
Hendrik F

Pour filtrer les valeurs nulles, essayez:

foo_df = df.filter( (df.foo==1) & (df.bar.isNull()) )

https://spark.Apache.org/docs/1.6.2/api/python/pyspark.sql.html#pyspark.sql.Column.isNull

13
johnaphun

Pourquoi ne filtre-t-il pas

Parce que c'est SQL et NULL indique des valeurs manquantes. Pour cette raison, toute comparaison avec NULL, autre que IS NULL et IS NOT NULL n'est pas défini. Vous avez besoin soit:

col("bar").isNull() | (col("bar") != 1)

ou

coalesce(col("bar") != 1, lit(True))

ou ( PySpark> = 2. ):

col("bar").eqNullSafe(1)

si vous voulez des comparaisons sûres nulles dans PySpark.

Également 'null' n'est pas un moyen valide pour introduire NULL littéral. Vous devez utiliser None pour indiquer les objets manquants.

from pyspark.sql.functions import col, coalesce, lit

df = spark.createDataFrame([
    ('a', 1, 1), ('a',1, None), ('b', 1, 1),
    ('c' ,1, None), ('d', None, 1),('e', 1, 1)
]).toDF('id', 'foo', 'bar')

df.where((col("foo") == 1) & (col("bar").isNull() | (col("bar") != 1))).show()

## +---+---+----+
## | id|foo| bar|
## +---+---+----+
## |  a|  1|null|
## |  c|  1|null|
## +---+---+----+

df.where((col("foo") == 1) & coalesce(col("bar") != 1, lit(True))).show()

## +---+---+----+
## | id|foo| bar|
## +---+---+----+
## |  a|  1|null|
## |  c|  1|null|
## +---+---+----+
12
zero323