web-dev-qa-db-fra.com

Spark Équivalent de IF Then ELSE

J'ai vu cette question plus tôt ici et j'en ai tiré des leçons. Cependant, je ne sais pas pourquoi j'obtiens une erreur quand je pense que cela devrait fonctionner.

Je veux créer une nouvelle colonne dans le Spark DataFrame selon certaines règles. Voici ce que j'ai écrit. Iris_spark est le bloc de données avec une variable catégorielle iris_spark avec trois catégories distinctes.

from pyspark.sql import functions as F

iris_spark_df = iris_spark.withColumn(
    "Class", 
   F.when(iris_spark.iris_class == 'Iris-setosa', 0, F.when(iris_spark.iris_class == 'Iris-versicolor',1)).otherwise(2))

Lance l'erreur suivante.

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-157-21818c7dc060> in <module>()
----> 1 iris_spark_df=iris_spark.withColumn("Class",F.when(iris_spark.iris_class=='Iris-setosa',0,F.when(iris_spark.iris_class=='Iris-versicolor',1)))

TypeError: when() takes exactly 2 arguments (3 given)


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-157-21818c7dc060> in <module>()
----> 1 iris_spark_df=iris_spark.withColumn("Class",F.when(iris_spark.iris_class=='Iris-setosa',0,F.when(iris_spark.iris_class=='Iris-versicolor',1)))

TypeError: when() takes exactly 2 arguments (3 given)

Une idée pourquoi?

15
Baktaawar

La structure correcte est soit:

(when(col("iris_class") == 'Iris-setosa', 0)
.when(col("iris_class") == 'Iris-versicolor', 1)
.otherwise(2))

ce qui équivaut à

CASE 
    WHEN (iris_class = 'Iris-setosa') THEN 0
    WHEN (iris_class = 'Iris-versicolor') THEN 1 
    ELSE 2
END

ou:

(when(col("iris_class") == 'Iris-setosa', 0)
    .otherwise(when(col("iris_class") == 'Iris-versicolor', 1)
        .otherwise(2)))

ce qui équivaut à:

CASE WHEN (iris_class = 'Iris-setosa') THEN 0 
     ELSE CASE WHEN (iris_class = 'Iris-versicolor') THEN 1 
               ELSE 2 
          END 
END

avec une syntaxe générale:

when(condition, value).when(...)

ou

when(condition, value).otherwise(...)

Vous avez probablement mélangé des choses avec Hive IF conditionnel:

IF(condition, if-true, if-false)

qui peut être utilisé uniquement en SQL brut avec le support Hive.

31
zero323

Il y a différentes manières de réaliser if-then-else.

  1. Utilisation de la fonction when dans l'API DataFrame. Vous pouvez spécifier la liste des conditions dans quand et également spécifier la valeur dont vous avez besoin. Vous pouvez également utiliser cette expression sous forme imbriquée.

  2. expr fonction. En utilisant la fonction "expr", vous pouvez passer une expression SQL dans expr. Exemple PFB. Ici, nous créons une nouvelle colonne "trimestre" basée sur la colonne du mois.

cond = """case when month > 9 then 'Q4'
            else case when month > 6 then 'Q3'
                else case when month > 3 then 'Q2'
                    else case when month > 0 then 'Q1'
                        end
                    end
                end
            end as quarter"""

newdf = df.withColumn("quarter", expr(cond))
  1. selectExpr fonction. Nous pouvons également utiliser la variante de la fonction select qui peut prendre l'expression SQL. Exemple PFB.
    cond = """case when month > 9 then 'Q4'
                else case when month > 6 then 'Q3'
                    else case when month > 3 then 'Q2'
                        else case when month > 0 then 'Q1'
                            end
                        end
                    end
                end as quarter"""

    newdf = df.selectExpr("*", cond)

4
neeraj bhadani

Instruction conditionnelle dans Spark

  • Utilisation de "dans le cas contraire" sur DataFrame
  • Utilisation de "cas où" sur DataFrame
  • Utilisation de l'opérateur && et

import org.Apache.spark.sql.functions.{when, _}
import spark.sqlContext.implicits._

val spark: SparkSession = SparkSession.builder().master("local[1]").appName("SparkByExamples.com").getOrCreate()

val data = List(("James ","","Smith","36636","M",60000),
        ("Michael ","Rose","","40288","M",70000),
        ("Robert ","","Williams","42114","",400000),
        ("Maria ","Anne","Jones","39192","F",500000),
        ("Jen","Mary","Brown","","F",0))

val cols = Seq("first_name","middle_name","last_name","dob","gender","salary")
val df = spark.createDataFrame(data).toDF(cols:_*)

1. Utilisation de "dans le cas contraire" sur DataFrame

Remplacez la valeur du sexe par une nouvelle valeur

val df1 = df.withColumn("new_gender", when(col("gender") === "M","Male")
      .when(col("gender") === "F","Female")
      .otherwise("Unknown"))

val df2 = df.select(col("*"), when(col("gender") === "M","Male")
      .when(col("gender") === "F","Female")
      .otherwise("Unknown").alias("new_gender"))

2. Utilisation de "case when" sur DataFrame

val df3 = df.withColumn("new_gender",
  expr("case when gender = 'M' then 'Male' " +
                   "when gender = 'F' then 'Female' " +
                   "else 'Unknown' end"))

Alternativement,

val df4 = df.select(col("*"),
      expr("case when gender = 'M' then 'Male' " +
                       "when gender = 'F' then 'Female' " +
                       "else 'Unknown' end").alias("new_gender"))

. Utilisation des opérateurs && et

val dataDF = Seq(
      (66, "a", "4"), (67, "a", "0"), (70, "b", "4"), (71, "d", "4"
      )).toDF("id", "code", "amt")
dataDF.withColumn("new_column",
       when(col("code") === "a" || col("code") === "d", "A")
      .when(col("code") === "b" && col("amt") === "4", "B")
      .otherwise("A1"))
      .show()

Sortie:

+---+----+---+----------+
| id|code|amt|new_column|
+---+----+---+----------+
| 66|   a|  4|         A|
| 67|   a|  0|         A|
| 70|   b|  4|         B|
| 71|   d|  4|         A|
+---+----+---+----------+
2
vj sreenivasan

vous pouvez utiliser ceci: if(exp1, exp2, exp3) inside spark.sql() où exp1 est la condition et si true donnez-moi exp2, sinon donnez-moi exp3.

maintenant la chose drôle avec si-autre imbriqué est. vous devez passer chaque exp à l'intérieur

brackets {"()"}
else it will raise error.

exemple:

if((1>2), (if (2>3), True, False), (False))
0
vermaji