Je devais obtenir une valeur d'une carte à partir d'une valeur de colonne comme clé et créer une nouvelle colonne
J'ai essayé ce qui suit
val testMap = Map("abc" -> "1234", "xyz" -> "3456") def checkthemap (testmap: Map[String, String], key: String) : String = { val value = testmap.get(key) if (value == null) "" else value.toString } val testDF = analysis .withColumn("test", lit(checkthemap(testMap,$"col")))
La méthode accepte la chaîne non la colonne. Comment modifier mon instruction withColumn pour envoyer la valeur de la colonne sous forme de chaîne à une méthode.
3 Réponses :
Je suggère d'utiliser une UDF (fonction définie par l'utilisateur) qui prend la colonne comme clé
pour la carte de recherche transmise pour renvoyer la valeur de la carte correspondante, comme indiqué ci-dessous:
import org.apache.spark.sql.functions._ import spark.implicits._ def getMapValue(m: Map[String, String], defaultValue: String) = udf{ (key: String) => m.getOrElse(key, defaultValue) } val df = Seq( (1, "a"), (2, "b"), (3, "c") ).toDF("id", "key") val lookupMap = Map("a" -> "xx", "c" -> "zz") df.withColumn("value", getMapValue(lookupMap, "")($"key")).show // +---+---+-----+ // | id|key|value| // +---+---+-----+ // | 1| a| xx| // | 2| b| | // | 3| c| zz| // +---+---+-----+
EDIT: Voir l'autre réponse pour une solution utilisant des fonctions Spark intégrées qui fonctionnent généralement mieux que les UDF.
La réponse acceptée est très inefficace et inutilement compliquée. Au lieu de cela, vous devez simplement traiter testMap
comme un littéral. Importez la
df.withColumn("value", coalesce(testMapCol($"col"), lit(""))
conversion suivante de la carte en colonne:
val testMapCol = typedLit(testMap)
et sélectionnez simplement:
import org.apache.spark.sql.functions.{coalesce, lit, typedLit}
Pour une raison quelconque, je ne souhaite pas créer de mappage vers une colonne ou un dataframe. Je veux y accéder depuis la méthode elle-même. Il y a t'il d'autres solutions?
@ user11425401 tout conseil sur ce problème UDF plz stackoverflow.com/questions/63935600/...
Je pense que vous pouvez utiliser la fonction intégrée element_at.
Sa définition est: Renvoie l'élément du tableau à un index donné en valeur si la colonne est un tableau. Renvoie la valeur de la clé donnée en valeur si la colonne est une carte.
import org.apache.spark.sql.functions.{element_at, col, typedLit} df.withColumn("value", element_at(typedLit(testMap), col("colName")))