我似乎正在遵循记录的方法来显示从具有模式的RDD转换的DF。但是很明显,我缺少一些重要的要点。然后如下:
# Original schema + Index for zipWithIndex with variations on this
schema = StructType(result_df.schema.fields[:] + [StructField("index", LongType(), True)])
rdd = result_df.rdd.zipWithIndex()
df = spark.createDataFrame(rdd, schema)
#df.select("*").show()
print(schema)
执行操作之前,该架构如下所示:
df:pyspark.sql.dataframe.DataFrame
ARRAY_COLS:array
element:string
index:long
模式:
StructType
(List(StructField
(ARRAY_COLS,ArrayType(StringType,true),false),
StructField(index,LongType,true)))
使用.show执行动作后,它立即爆炸。在这种情况下,我的工作是动态的,但并不是必须的。
完整列表
from functools import reduce
from pyspark.sql.functions import lower, col, lit, concat, split
from pyspark.sql.types import *
from pyspark.sql import Row
from pyspark.sql import functions as f
source_df = spark.createDataFrame(
[
(1, 11, 111),
(2, 22, 222)
],
["colA", "colB", "colC"]
)
intermediate_df = (reduce(
lambda df, col_name: df.withColumn(col_name, concat(lit(col_name), lit("_"), col(col_name))),
source_df.columns,
source_df
) )
intermediate_df.show(truncate=False)
allCols = [x for x in intermediate_df.columns]
result_df = intermediate_df.select(f.concat_ws(',', *allCols).alias('CONCAT_COLS'))
result_df.show(truncate=False)
result_df = result_df.select(split(col("CONCAT_COLS"), ",\s*").alias("ARRAY_COLS"))
result_df.show(truncate=False)
#######
schema = StructType(result_df.schema.fields[:] + [StructField("index", LongType(), True)])
rdd = result_df.rdd.zipWithIndex()
df = spark.createDataFrame(rdd, schema)
df.select("*").show()
print(schema)
答案 0 :(得分:1)
如果您查看rdd
,问题将更加清楚:
print(rdd.collect())
#[(Row(ARRAY_COLS=[u'colA_1', u'colB_11', u'colC_111']), 0),
# (Row(ARRAY_COLS=[u'colA_2', u'colB_22', u'colC_222']), 1)]
请注意,它是一个包含Row
对象和索引的元组。
我看到了两种选择:
1)使用元组理解将值从Row
和map
的{{1}}提取到与rdd
匹配的元组:
schema
这将使用每个记录的内容创建一个新的rdd1 = rdd.map(
lambda row: tuple(row[0].asDict()[c] for c in schema.fieldNames()[:-1]) + (row[1],)
)
df1 = spark.createDataFrame(rdd1, schema)
df1.show(truncate=False)
#+---------------------------+-----+
#|ARRAY_COLS |index|
#+---------------------------+-----+
#|[colA_1, colB_11, colC_111]|0 |
#|[colA_2, colB_22, colC_222]|1 |
#+---------------------------+-----+
:
tuple
2)通过添加print(rdd1.collect())
#[([u'colA_1', u'colB_11', u'colC_111'], 0),
# ([u'colA_2', u'colB_22', u'colC_222'], 1)]
并解压缩现有Row
来构建新的index
:
Row
现在每个记录都是一个rdd2 = rdd.map(lambda row: Row(index=0, **row[0].asDict()))
df2 = spark.createDataFrame(rdd2, schema)
df2.show(truncate=False)
#+---------------------------+-----+
#|ARRAY_COLS |index|
#+---------------------------+-----+
#|[colA_1, colB_11, colC_111]|0 |
#|[colA_2, colB_22, colC_222]|1 |
#+---------------------------+-----+
,其中添加了Row
:
index
但是,因此,您无需在对print(rdd2.collect())
#[Row(ARRAY_COLS=[u'colA_1', u'colB_11', u'colC_111'], index=0),
# Row(ARRAY_COLS=[u'colA_2', u'colB_22', u'colC_222'], index=0)]
的调用中使用schema
:
createDataFrame
方法1使用您已经定义的现有spark.createDataFrame(rdd2).show()
#+---------------------------+-----+
#|ARRAY_COLS |index|
#+---------------------------+-----+
#|[colA_1, colB_11, colC_111]|0 |
#|[colA_2, colB_22, colC_222]|1 |
#+---------------------------+-----+
,而方法2可能在代码方面更紧凑(但需要硬编码的schema
)。