scala - started - spark python
¿Es posible alias columnas programáticamente en spark sql? (4)
Resulta def toDF(colNames: String*): DataFrame
hace exactamente eso. Pegado de la documentación 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"
En spark SQL (quizás solo HiveQL) uno puede hacer:
select sex, avg(age) as avg_age
from humans
group by sex
lo que daría como resultado un DataFrame
con columnas llamadas "sex"
y "avg_age"
.
¿Cómo se puede alias a avg(age)
a "avg_age"
sin usar SQL textual?
Editar: Después de la respuesta de zero323, necesito agregar la restricción que:
El nombre de la columna a ser renombrada puede no ser conocido / garantizado o incluso direccionable . En SQL textual, el uso de "seleccionar EXPR como NAME" elimina el requisito de tener un nombre intermedio para EXPR. Este también es el caso en el ejemplo anterior, donde "avg (edad)" podría obtener una variedad de nombres generados automáticamente (que también varían entre lanzamientos de chispa y backends de contexto SQL).
Las columnas anónimas, como la que generaría avg(age)
sin AS avg_age
, recibirán automáticamente nombres asignados. Como usted señala en su pregunta, los nombres son específicos de la implementación, generados por una estrategia de nombres. Si es necesario, puede escribir un código que olfatea el entorno y crea una estrategia apropiada de descubrimiento y cambio de nombre basada en la estrategia de nomenclatura específica. No hay muchos de ellos.
En Spark 1.4.1 con HiveContext
, el formato es "_c N " donde N es la posición de la columna anónima en la tabla. En tu caso, el nombre sería _c1
.
Si prefiere cambiar el nombre de una sola columna, puede usar el método withColumnRenamed
:
case class Person(name: String, age: Int)
val df = sqlContext.createDataFrame(
Person("Alice", 2) :: Person("Bob", 5) :: Nil)
df.withColumnRenamed("name", "first_name")
Alternativamente, puede usar el método de alias
:
import org.apache.spark.sql.functions.avg
df.select(avg($"age").alias("average_age"))
Puedes llevarlo más lejos con un pequeño ayudante:
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")))
Supongamos que human_df
es el DataFrame para humanos. Desde Spark 1.3:
human_df.groupBy("sex").agg(avg("age").alias("avg_age"))