如何将PySpark RDD线性列表转换为DataFrame?

时间:2019-04-07 12:25:55

标签: apache-spark dataframe pyspark rdd

我想将线性列表转换为数据框。 即给出以下列表,

a = ["a1", "a2", "a3", b1", "b2", "b3", "c1", "c2", "c3"]

预期结果是

+--------------------+
| col1 | col2 | col3 |
+--------------------+
|  a1  |  a2  |  a3  |
|  b1  |  b2  |  b3  |
|  c1  |  c2  |  c3  |
+--------------------+

我尝试了以下操作,但出现了错误。

from pyspark.sql.types import *

a = ["a1", "a2", "a3", "b1", "b2", "b3", "c1", "c2", "c3"]

rdd = sc.parallelize(a)

schema = StructType([
     StructField("a", StringType(), True),
     StructField("b", StringType(), True),
     StructField("c", StringType(), True)
     ])

df = sqlContext.createDataFrame(rdd, schema)

df.show()

最后一个show()语句收到错误“作业由于阶段失败而中止”。 请有人告诉我解决方案? 谢谢。

2 个答案:

答案 0 :(得分:1)

根据您的comment,我假设您从rdd开始,而不是列表。

我进一步假设您正在根据rdd的索引确定顺序。如果这些假设正确,则可以使用zipWithIndex()向每条记录添加行号。

然后将行号除以3(使用整数除法)以每3个连续记录分组。接下来使用groupByKey()将具有相同key的记录聚合到一个元组中。

最后,放下键并呼叫toDF()

rdd.zipWithIndex()\
    .map(lambda row: (row[1]//3, row[0]))\
    .groupByKey()\
    .map(lambda row: tuple(row[1]))\
    .toDF(["a", "b", "c"])\
    .show()
#+---+---+---+
#|  a|  b|  c|
#+---+---+---+
#| a1| a2| a3|
#| c1| c2| c3|
#| b1| b2| b3|
#+---+---+---+

答案 1 :(得分:0)

这是一种应该符合您的条件的方法

# First get a 1 column DF
df = sql.createDataFrame(sc.parallelize(a).map(lambda x: [x]), schema=['col'])
# split each value into a number and letter e.g. 'a1' --> ['a','1']) 
df = df.withColumn('letter', f.split('col', '').getItem(0))
df = df.withColumn('number', f.split('col', '').getItem(1))

# Now pivot to get what you want (dropping extraneous columns and ordering 
# to get exact output

output = (df.groupBy('letter')
          .pivot('number')
          .agg(f.first('col'))
          .select([f.col(column).alias('col%s'%(column)) for column in ['1','2','3']])
          .orderBy('col1')
          .drop('letter'))