Solución:
No es posible utilizar un solo withColumnRenamed
llama.
-
Puedes usar
DataFrame.toDF
método*data.toDF('x3', 'x4')
o
new_names = ['x3', 'x4'] data.toDF(*new_names)
-
También es posible cambiar el nombre con un simple
select
:from pyspark.sql.functions import col mapping = dict(zip(['x1', 'x2'], ['x3', 'x4'])) data.select([col(c).alias(mapping.get(c, c)) for c in data.columns])
Del mismo modo, en Scala puede:
-
Cambiar el nombre de todas las columnas:
val newNames = Seq("x3", "x4") data.toDF(newNames: _*)
-
Cambiar el nombre del mapeo con
select
:val mapping = Map("x1" -> "x3", "x2" -> "x4") df.select( df.columns.map(c => df(c).alias(mapping.get(c).getOrElse(c))): _* )
o
foldLeft
+withColumnRenamed
mapping.foldLeft(data){ case (data, (oldName, newName)) => data.withColumnRenamed(oldName, newName) }
* No confundir con RDD.toDF
que no es una función variada, y toma los nombres de las columnas como una lista,
Tampoco pude encontrar una solución fácil de pyspark, así que construí la mía propia, similar a la de pandas df.rename(columns={'old_name_1':'new_name_1', 'old_name_2':'new_name_2'})
.
def rename_columns(df, columns):
if isinstance(columns, dict):
for old_name, new_name in columns.items():
df = df.withColumnRenamed(old_name, new_name)
return df
else:
raise ValueError("'columns' should be a dict, like {'old_name_1':'new_name_1', 'old_name_2':'new_name_2'}")
Entonces tu solución se verá como data = rename_columns(data, {'x1': 'x3', 'x2': 'x4'})
Me ahorra algunas líneas de código, espero que también te ayude.
¿Por qué desea realizarlo en una sola línea si imprime el plan de ejecución? En realidad, se hace en una sola línea.
data = spark.createDataFrame([(1,2), (3,4)], ['x1', 'x2'])
data = (data
.withColumnRenamed('x1','x3')
.withColumnRenamed('x2', 'x4'))
data.explain()
PRODUCCIÓN
== Physical Plan ==
*(1) Project [x1#1548L AS x3#1552L, x2#1549L AS x4#1555L]
+- Scan ExistingRDD[x1#1548L,x2#1549L]
si desea hacerlo con una tupla de lista, puede usar una función de mapa simple
data = spark.createDataFrame([(1,2), (3,4)], ['x1', 'x2'])
new_names = [("x1","x3"),("x2","x4")]
data = data.select(list(
map(lambda old,new:F.col(old).alias(new),*zip(*new_names))
))
data.explain()
todavía tiene el mismo plan
PRODUCCIÓN
== Physical Plan ==
*(1) Project [x1#1650L AS x3#1654L, x2#1651L AS x4#1655L]
+- Scan ExistingRDD[x1#1650L,x2#1651L]