如何制作PySpark Row对象的变异副本?

时间:2017-12-20 20:33:34

标签: pyspark spark-dataframe rdd

from pyspark.sql import Row

一个Row对象是不可变的。它可以转换为Python字典然后变异然后返回到Row对象。有没有办法制作一个可变或变异的副本,而不转换为字典并返回行?

在mapPartitions中运行的函数中需要这样做。

3 个答案:

答案 0 :(得分:0)

根据您的实际用例,一种可能性就是从现有用户创建一个新的Row对象。

from pyspark.sql import Row
R = Row('a', 'b', 'c')
r = R(1,2,3)

假设我们要将a更改为3 r,从r创建一个新的Row对象:

R(3, r.b, r.c)
# Row(a=3, b=2, c=3)

虽然r仍然是:

r
# Row(a=1, b=2, c=3)

答案 1 :(得分:0)

以下是制作变异副本的动态解决方案:

from pyspark.sql import Row

def copy(row, **kwargs):
    dict = {}
    for attr in list(row.__fields__):
        dict[attr] = row[attr]

    for key, value in kwargs.items():
        dict[key] = value 

    return Row(**dict)

row =  Row(name="foo", age=45)
print(row) #Row(age=45, name='foo')

new_row = copy(row, name="bar")
print(new_row) #Row(age=45, name='bar')

答案 2 :(得分:0)

row.asDict()**dict都不会保留字段的顺序。请注意,在python 3.6+中,这可能会改变。见PEP 468

与@hahmed所说的相似。这会动态创建一个带有与传入的行相同的模式的变异行BUT。

from pyspark.sql import Row
from collections import OrderedDict

def copy(row, **kwargs):
    d = OrderedDict(zip(row.__fields__, row)) #note this is not recursive
    for key, value in kwargs.iteritems():
        d[key]=value
    MyRow = Row(row.__fields__)
    return MyRow(*d.values())

如果您需要将数据帧转换为RDD然后再将其设为DF

,这非常有用

例如

df_schema = df.schema
rdd = df_schema.rdd.map(lambda row: copy(row, field=newvalue))
new_df = spark.createDataFrame(rdd, df_schema)