Dataframe 使用列表并替换pyspark列
假设我有一个列表new_id_acc=[6,8,1,2,4],我有PySpark数据帧 像 我想用新的_id_acc值替换pyspark列id_acc,如何实现和执行此操作。 我试过了,发现lit()只能用于常量 值,但未找到列表的任何操作 更换后,我希望我的PySpark数据框看起来像这样Dataframe 使用列表并替换pyspark列,dataframe,pyspark,Dataframe,Pyspark,假设我有一个列表new_id_acc=[6,8,1,2,4],我有PySpark数据帧 像 我想用新的_id_acc值替换pyspark列id_acc,如何实现和执行此操作。 我试过了,发现lit()只能用于常量 值,但未找到列表的任何操作 更换后,我希望我的PySpark数据框看起来像这样 id_acc | name | 6 | ABC | 8 | XYZ | 1 | KBC | 2 | RAH | 4
id_acc | name |
6 | ABC |
8 | XYZ |
1 | KBC |
2 | RAH |
4 | SPD |
答案可能很长,但它有效
df = spark.sparkContext.parallelize([(10,'ABC'),(20,'XYZ'),(21,'KBC'),(34,'ABC'),(19,'SPD')]).toDF(('id_acc', 'name'))
df.show()
+------+----+
|id_acc|name|
+------+----+
| 10| ABC|
| 20| XYZ|
| 21| KBC|
| 34| ABC|
| 19| SPD|
+------+----+
new_id_acc = [6,8,1,2,4]
indx = ['ABC','XYZ','KBC','ABC','SPD']
from pyspark.sql.types import *
myschema= StructType([ StructField("indx", StringType(), True),StructField("new_id_ac", IntegerType(), True)])
df1=spark.createDataFrame(zip(indx,new_id_acc),schema = myschema)
df1.show()
+----+---------+
|indx|new_id_ac|
+----+---------+
| ABC| 6|
| XYZ| 8|
| KBC| 1|
| ABC| 2|
| SPD| 4|
+----+---------+
dfnew = df.join(df1, df.name == df1.indx,how='left').drop(df1.indx).select('new_id_ac','name').sort('name').dropDuplicates(['new_id_ac'])
dfnew.show()
+---------+----+
|new_id_ac|name|
+---------+----+
| 1| KBC|
| 6| ABC|
| 4| SPD|
| 8| XYZ|
| 2| ABC|
+---------+----+
其思想是创建一列连续的序列号/行号,然后使用它们从列表中获取相应的值
# Creating the requisite DataFrame
from pyspark.sql.functions import row_number,lit, udf
from pyspark.sql.window import Window
valuesCol = [(10,'ABC'),(20,'XYZ'),(21,'KBC'),(34,'RAH'),(19,'SPD')]
df = spark.createDataFrame(valuesCol,['id_acc','name'])
df.show()
+------+----+
|id_acc|name|
+------+----+
| 10| ABC|
| 20| XYZ|
| 21| KBC|
| 34| RAH|
| 19| SPD|
+------+----+
您可以像“完成”一样创建行/序列号
请注意,下面的A
只是一个dummy
值,因为我们不需要对tha值进行排序。我们只需要行号
w = Window().orderBy(lit('A'))
df = df.withColumn('serial_number', row_number().over(w))
df.show()
+------+----+-------------+
|id_acc|name|serial_number|
+------+----+-------------+
| 10| ABC| 1|
| 20| XYZ| 2|
| 21| KBC| 3|
| 34| RAH| 4|
| 19| SPD| 5|
+------+----+-------------+
作为最后一步,我们将使用行号
从OP
提供的列表中访问元素。为此,我们使用
替换的逻辑应该是什么,还是希望为所有行填充[6,8,1,2,4]?请发布替换后数据帧的外观。我已经添加了新数据帧的外观,非常感谢您的帮助。如果您的数据帧分布在多台计算机上,则无法保证数据帧行的顺序保持不变。您对列表的第一项替换数据帧的第一条记录是否满意(由于没有排序,数据帧记录的顺序每次都可能更改)第二项替换数据帧的第二条记录,或者您是否有订购/排序数据帧记录的逻辑?如果我们在名称列中有相同的名称,例如假设new_id_ac'2'与'6'同名,该怎么办?Hi@RAHULVISHWAKARMA我已更新解决方案,查看这是否是您的要求。请注意,您的indx列表与df.name相同柱
w = Window().orderBy(lit('A'))
df = df.withColumn('serial_number', row_number().over(w))
df.show()
+------+----+-------------+
|id_acc|name|serial_number|
+------+----+-------------+
| 10| ABC| 1|
| 20| XYZ| 2|
| 21| KBC| 3|
| 34| RAH| 4|
| 19| SPD| 5|
+------+----+-------------+
new_id_acc = [6,8,1,2,4]
mapping = udf(lambda x: new_id_acc[x-1])
df = df.withColumn('id_acc', mapping(df.serial_number)).drop('serial_number')
df.show()
+------+----+
|id_acc|name|
+------+----+
| 6| ABC|
| 8| XYZ|
| 1| KBC|
| 2| RAH|
| 4| SPD|
+------+----+