web-dev-qa-db-fra.com

Est-il possible d'aliaser des colonnes par programmation dans spark sql?

En spark SQL (peut-être seulement HiveQL) on peut faire:

select sex, avg(age) as avg_age
from humans
group by sex

ce qui entraînerait un DataFrame avec des colonnes nommées "sex" et "avg_age".

Comment alias avg(age) avec "avg_age" Sans utiliser SQL textuel?

Edit: Après la réponse de zero323, je dois ajouter la contrainte qui:

Le nom de la colonne à renommer peut ne pas être connu/garanti ou même adressable . Dans SQL textuel, l'utilisation de "sélectionner EXPR comme NOM" supprime la nécessité d'avoir un nom intermédiaire pour EXPR. C'est également le cas dans l'exemple ci-dessus, où "avg (age)" pourrait obtenir une variété de noms générés automatiquement (qui varient également entre spark releases et backends sql-context).

20
Prikso NAI

Il s'avère que def toDF(colNames: String*): DataFrame fait exactement cela. Collage de la documentation 2.11.7:

def toDF(colNames: String*): DataFrame

Returns a new DataFrame with columns renamed. This can be quite
convenient in conversion from a RDD of tuples into a DataFrame
with meaningful names. For example:

    val rdd: RDD[(Int, String)] = ...
    rdd.toDF()  // this implicit conversion creates a DataFrame
                // with column name _1 and _2
    rdd.toDF("id", "name")  // this creates a DataFrame with
                            // column name "id" and "name"
10
Prikso NAI

Supposons human_df est le DataFrame pour les humains. Depuis Spark 1.3:

human_df.groupBy("sex").agg(avg("age").alias("avg_age"))
32
Robert Chevallier

Si vous préférez renommer une seule colonne, il est possible d'utiliser la méthode withColumnRenamed:

case class Person(name: String, age: Int)

val df = sqlContext.createDataFrame(
    Person("Alice", 2) :: Person("Bob", 5) :: Nil) 
df.withColumnRenamed("name", "first_name")

Vous pouvez également utiliser la méthode alias:

import org.Apache.spark.sql.functions.avg

df.select(avg($"age").alias("average_age")) 

Vous pouvez aller plus loin avec une petite aide:

import org.Apache.spark.sql.Column

def normalizeName(c: Column) = {
  val pattern = "\\W+".r
  c.alias(pattern.replaceAllIn(c.toString, "_"))
}

df.select(normalizeName(avg($"age")))
17
zero323

Colonnes anonymes, telles que celles qui seraient générées par avg(age) sans AS avg_age, obtenez les noms attribués automatiquement. Comme vous le signalez dans votre question, les noms sont spécifiques à l'implémentation, générés par une stratégie de nommage. Si nécessaire, vous pouvez écrire du code qui renifle l'environnement et instancie une stratégie de découverte et de renommage appropriée basée sur la stratégie de nommage spécifique. Il n'y en a pas beaucoup.

Dans Spark 1.4.1 avec HiveContext, le format est "_c N " où N est la position de la colonne anonyme dans le tableau. Dans votre cas, le nom serait _c1.

1
Sim