我正在Spark中创建Row对象。我不希望我的字段按字母顺序排序。但是,如果我执行以下操作,它们将按字母顺序排序。
row = Row(foo=1, bar=2)
然后,它会创建一个如下所示的对象:
Row(bar=2, foo=1)
然后,当我在此对象上创建数据帧时,列顺序将首先是条形图,其次是 foo,而我宁愿以相反的方式使用它。
我知道我可以使用"_1"和"_2"(分别用于"foo"和"bar"),然后分配一个模式(使用适当的"foo"和"bar"名称)。但是有没有办法阻止 Row 对象对它们进行排序?
Spark>= 3.0
SPARK-29748 已删除字段排序(删除 PySpark SQL 行创建中的字段排序)导出),但传统模式除外,当设置了以下环境变量时:
PYSPARK_ROW_FIELD_SORTING_ENABLED=true
火花<3.0
但是有没有办法阻止 Row 对象对它们进行排序?
没有。如果您提供kwargs
参数将按名称排序。确定性行为需要排序,因为 Python 3.6 之前的 Python 不会保留关键字参数的顺序。
只需使用普通元组:
rdd = sc.parallelize([(1, 2)])
并将架构作为参数传递给RDD.toDF
(不要与DataFrame.toDF
混淆):
rdd.toDF(["foo", "bar"])
或createDataFrame
:
from pyspark.sql.types import *
spark.createDataFrame(rdd, ["foo", "bar"])
# With full schema
schema = StructType([
StructField("foo", IntegerType(), False),
StructField("bar", IntegerType(), False)])
spark.createDataFrame(rdd, schema)
您还可以使用namedtuples
:
from collections import namedtuple
FooBar = namedtuple("FooBar", ["foo", "bar"])
spark.createDataFrame([FooBar(foo=1, bar=2)])
最后,您可以按select
对列进行排序:
sc.parallelize([Row(foo=1, bar=2)]).toDF().select("foo", "bar")
来自文档:
Row 也可以用来创建另一个类似 Row 的类,然后它可以用来创建 Row 对象
在这种情况下,将保存列的顺序:
>>> FooRow = Row('foo', 'bar')
>>> row = FooRow(1, 2)
>>> spark.createDataFrame([row]).dtypes
[('foo', 'bigint'), ('bar', 'bigint')]
如何对原始架构进行排序以匹配 RDD 的字母顺序:
schema_sorted = StructType()
structfield_list_sorted = sorted(df.schema, key=lambda x: x.name)
for item in structfield_list_sorted:
schema_sorted.add(item)