下面的数据框是一个名为的 temp_table: 'table_name' 。
您将如何使用 spark.sql() 为所有列提供前缀?
root
|-- MAIN_COL: struct (nullable = true)
| |-- a: string (nullable = true)
| |-- b: string (nullable = true)
| |-- c: string (nullable = true)
| |-- d: string (nullable = true)
| |-- f: long (nullable = true)
| |-- g: long (nullable = true)
| |-- h: long (nullable = true)
| |-- j: long (nullable = true)
下面的查询
spark.sql("select MAIN_COL.* from table_name")
返回名为 a,b,c... 的列,但是如何使它们看起来都像例如pre_a、pre_b、pre_c?
想要避免一一选择和给它们别名。如果我有 30 列怎么办?
我希望自定义 UDF 可以解决它在 SQL 中使用的问题,但真的不知道如何处理。
# Generate a pandas DataFrame
import pandas as pd
a_dict={
'a':[1,2,3,4,5],
'b':[1,2,3,4,5],
'c':[1,2,3,4,5],
'e':list('abcde'),
'f':list('abcde'),
'g':list('abcde')
}
pandas_df=pd.DataFrame(a_dict)
# Create a Spark DataFrame from a pandas DataFrame using Arrow
spark.conf.set("spark.sql.execution.arrow.enabled", "true")
df = spark.createDataFrame(pandas_df)
#struct
from pyspark.sql.functions import struct
main=df.select(struct(df.columns).alias("MAIN_COL"))
最佳答案
这是一种遍历字段并动态修改其名称的方法。第一次使用 main.schema.fields[0].dataType.fields
访问目标字段。接下来使用python map
前置 pre_
到每个字段:
from pyspark.sql.types import *
from pyspark.sql.functions import col
inner_fields = main.schema.fields[0].dataType.fields
# [StructField(a,LongType,true),
# StructField(b,LongType,true),
# StructField(c,LongType,true),
# StructField(e,StringType,true),
# StructField(f,StringType,true),
# StructField(g,StringType,true)]
pre_cols = list(map(lambda sf: StructField(f"pre_{sf.name}", sf.dataType, sf.nullable), inner_fields))
new_schema = StructType(pre_cols)
main.select(col("MAIN_COL").cast(new_schema)).printSchema()
# root
# |-- MAIN_COL: struct (nullable = false)
# | |-- pre_a: long (nullable = true)
# | |-- pre_b: long (nullable = true)
# | |-- pre_c: long (nullable = true)
# | |-- pre_e: string (nullable = true)
# | |-- pre_f: string (nullable = true)
# | |-- pre_g: string (nullable = true)
最后,您可以使用
cast
使用@Mahesh 已经提到的新模式。
关于python - 使用 'struct_name.*' 选择时为所有列提供前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59960236/