将列表的列表作为列追加到PySpark的数据框(连接两个没有公共列的数据框)

时间:2019-11-04 22:22:55

标签: python dataframe pyspark

我在Pyspark中有一些数据框:

from pyspark.sql import SQLContext, SparkSession

spark = SparkSession.builder.getOrCreate()
sqlcontext = SQLContext(spark)
df = sqlcontext.createDataFrame([['a'],['b'],['c'],['d'],['e']], ['id'])
df.show()

+---+
| id|
+---+
|  a|
|  b|
|  c|
|  d|
|  e|
+---+

我有一个列表列表:

l = [[1,1], [2,2], [3,3], [4,4], [5,5]]

是否可以将此列表作为列附加到df?也就是说,l的第一个元素应该出现在df的第一行旁边,l的第二个元素应该出现在df的第二行旁边,依此类推。看起来像这样:

+----+---+--+
|  id|     l|
+----+---+--+
|   a| [1,1]|
|   b| [2,2]|
|   c| [3,3]|
|   d| [4,4]|
|   e| [5,5]|
+----+---+--+

3 个答案:

答案 0 :(得分:2)

UDF通常很慢,但是不使用任何UDF的更有效的方法是:

import pyspark.sql.functions as F

ldf = spark.createDataFrame(l, schema = "array<int>")

df1 = df.withColumn("m_id", F.monotonically_increasing_id())
df2 = ldf.withColumn("m_id", F.monotonically_increasing_id()) 

df3 = df2.join(df1, "m_id", "outer").drop("m_id") 
df3.select("id", "value").show()
+---+------+
| id| value|
+---+------+
|  a|[1, 1]|
|  b|[2, 2]|
|  d|[4, 4]|
|  c|[3, 3]|
|  e|[5, 5]|
+---+------+

答案 1 :(得分:0)

假设您在dflistdf.count==len(l))中的行数相同。

您可以在row_id上添加df(以指定顺序),然​​后在此基础上访问list(l)上的项目。

from pyspark.sql.functions import row_number, lit
from pyspark.sql.window import *

df = df.withColumn("row_num", row_number().over(Window().orderBy(lit('A'))))
df.show()

上面的代码如下:

+---+-------+
| id|row_num|
+---+-------+
|  1|      1|
|  2|      2|
|  3|      3|
|  4|      4|
|  5|      5|
+---+-------+

然后,您可以迭代df并访问列表中的指定索引:

def map_df(row):
  return (row.id, l[row.row_num-1])

new_df = df.rdd.map(map_df).toDF(["id", "l"])

new_df.show()

输出:

+---+------+
| id|     l|
+---+------+
|  1|[1, 1]|
|  2|[2, 2]|
|  3|[3, 3]|
|  4|[4, 4]|
|  5|[5, 5]|
+---+------+

答案 2 :(得分:0)

多亏了Cesar的回答,我弄清楚了如何在不使数据帧成为RDD并返回的情况下进行操作。会是这样的:

from pyspark.sql import SQLContext, SparkSession
from pyspark.sql.functions import row_number, lit, udf
from pyspark.sql.window import Window
from pyspark.sql.types import ArrayType, FloatType, IntegerType

spark = SparkSession.builder.getOrCreate()
sqlcontext = SQLContext(spark)
df = sqlcontext.createDataFrame([['a'],['b'],['c'],['d'],['e']], ['id'])

df = df.withColumn("row_num", row_number().over(Window().orderBy(lit('A'))))

new_col = [[1.,1.], [2.,2.], [3.,3.], [4.,4.], [5.,5.]]

map_list_to_column = udf(lambda row_num: new_col[row_num -1], ArrayType(FloatType()))

df.withColumn('new_col', map_list_to_column(df.row_num)).drop('row_num').show()