升级 PySpark#

从 PySpark 4.0 升级到 4.1#

  • 在 Spark 4.1 中,PySpark 停止了对 Python 3.9 的支持。

  • 在 Spark 4.1 中,PySpark 对 PyArrow 的最低支持版本从 11.0.0 提高到了 15.0.0。

  • 在 Spark 4.1 中,PySpark 对 Pandas 的最低支持版本从 2.0.0 提高到了 2.2.0。

  • 在 Spark 4.1 中,Spark Connect Python 客户端上的 DataFrame['name'] 不再立即验证列名。若要恢复旧行为,请将 PYSPARK_VALIDATE_COLUMN_NAME_LEGACY 环境变量设置为 1

  • 在 Spark 4.1 中,Arrow 优化的 Python UDF 支持 UDT 输入/输出,不再回退到常规 UDF。若要恢复旧行为,请将 spark.sql.execution.pythonUDF.arrow.legacy.fallbackOnUDT 设置为 true

  • 在 Spark 4.1 中,当启用了 spark.sql.execution.pythonUDF.arrow.enabled 时,移除了不必要的向 pandas 实例的转换。因此,当产生的输出模式与指定模式不同时,类型强制转换会发生变化。若要恢复之前的行为,请启用 spark.sql.legacy.execution.pythonUDF.pandas.conversion.enabled

  • 在 Spark 4.1 中,当启用了 spark.sql.execution.pythonUDTF.arrow.enabled 时,移除了不必要的向 pandas 实例的转换。因此,当产生的输出模式与指定模式不同时,类型强制转换会发生变化。若要恢复之前的行为,请启用 spark.sql.legacy.execution.pythonUDTF.pandas.conversion.enabled

  • 在 Spark 4.1 中,BinaryType 数据类型在 PySpark 中默认统一映射为 Python 的 bytes 类型。若要恢复之前的行为,请将 spark.sql.execution.pyspark.binaryAsBytes 设置为 false。Spark 4.1.0 之前的行为如下表所示:

    情况

    BinaryType 的 Python 类型

    无 Arrow 优化的常规 UDF 和 UDTF

    bytearray

    DataFrame API(Spark Classic 和 Spark Connect)

    bytearray

    数据源

    bytearray

    带有不必要转换至 pandas 实例的 Arrow 优化 UDF 和 UDTF

    bytes

  • 在 Spark 4.1 中,默认启用了 spark.sql.execution.pandas.convertToArrowArraySafely 配置。启用此设置后,PyArrow 会针对不安全的转换(如整数溢出、浮点数截断和精度损失)抛出错误。此更改会影响启用了 Arrow 的 UDF/pandas_udfs 的返回数据序列化,以及 PySpark DataFrame 的创建。若要恢复之前的行为,请将该配置设置为 false

  • 在 Spark 4.1 中,当 compute.ansi_mode_support 设置为 True(默认)时,Spark 上的 pandas API 在 ANSI 模式下工作。安全保护选项 compute.fail_on_ansi_mode 仍然可用,但仅在 compute.ansi_mode_supportFalse 时生效。

从 PySpark 3.5 升级到 4.0#

  • 在 Spark 4.0 中,PySpark 停止了对 Python 3.8 的支持。

  • 在 Spark 4.0 中,PySpark 对 Pandas 的最低支持版本从 1.0.5 提高到了 2.0.0。

  • 在 Spark 4.0 中,PySpark 对 Numpy 的最低支持版本从 1.15 提高到了 1.21。

  • 在 Spark 4.0 中,PySpark 对 PyArrow 的最低支持版本从 4.0.0 提高到了 11.0.0。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 Int64IndexFloat64Index,应直接使用 Index

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrame.iteritems,请改用 DataFrame.items

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 Series.iteritems,请改用 Series.items

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrame.append,请改用 ps.concat

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 Series.append,请改用 ps.concat

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrame.mad

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 Series.mad

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 Index.factorizeSeries.factorize 中的 na_sentinel 参数,请改用 use_na_sentinel

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 Categorical.add_categoriesCategorical.remove_categories 等方法中的 inplace 参数。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 CategoricalIndex.add_categories 等方法中的 inplace 参数。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 ps.date_range 中的 closed 参数。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrame.between_time 中的 include_startinclude_end 参数,请改用 inclusive

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 Series.between_time 中的 include_startinclude_end 参数,请改用 inclusive

  • 在 Spark 4.0 中,Spark 上的 pandas API 中 DatetimeIndex 的各种日期时间属性(day, month, year 等)现在为 int32 而不是 int64

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrame.plotSeries.plot 中的 sort_columns 参数。

  • 在 Spark 4.0 中,Spark 上的 pandas API 中 Series.str.replaceregex 参数默认值从 True 改为 False。此外,当 regex=True 时,单字符 pat 现在被视为正则表达式,而不是字符串字面量。

  • 在 Spark 4.0 中,Spark 上的 pandas API 中所有对象的 value_counts 结果名称设置为 'count'(如果传入 normalize=True,则为 'proportion'),索引将以原始对象命名。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 ps.read_csvps.read_excel 中的 squeeze 参数。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrame.info 中的 null_counts 参数,请改用 show_counts

  • 在 Spark 4.0 中,Spark 上的 pandas API 中 MultiIndex.append 的结果不再保留索引名称。

  • 在 Spark 4.0 中,Spark 上的 pandas API 中列表相关的 DataFrameGroupBy.agg 遵循 as_index=False

  • 在 Spark 4.0 中,Spark 上的 pandas API 中 DataFrame.stack 保证了现有列的顺序,而不是按字典顺序排序。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 Series.betweeninclusive 参数中的 TrueFalse,请分别改用 bothneither

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 Index.asi8,请改用 Index.astype

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 Index.is_type_compatible,请改用 Index.isin

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrame.to_latexSeries.to_latex 中的 col_space 参数。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrame.to_spark_io,请改用 DataFrame.spark.to_spark_io

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 Series.is_monotonicIndex.is_monotonic,请分别改用 Series.is_monotonic_increasingIndex.is_monotonic_increasing

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrame.get_dtype_counts,请改用 DataFrame.dtypes.value_counts()

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrame.to_excelSeries.to_excel 中的 encoding 参数。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrame.to_excelSeries.to_excel 中的 verbose 参数。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 read_csv 中的 mangle_dupe_cols 参数。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrameGroupBy.backfill,请改用 DataFrameGroupBy.bfill

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrameGroupBy.pad,请改用 DataFrameGroupBy.ffill

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 Index.is_all_dates

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 read_excel 中的 convert_float 参数。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 read_excel 中的 mangle_dupe_cols 参数。

  • 在 Spark 4.0 中,Spark 上的 pandas API 移除了 DataFrame.koalas,请改用 DataFrame.pandas_on_spark

  • 在 Spark 4.0 中,PySpark 移除了 DataFrame.to_koalas,请改用 DataFrame.pandas_api

  • 在 Spark 4.0 中,PySpark 移除了 DataFrame.to_pandas_on_spark,请改用 DataFrame.pandas_api

  • 在 Spark 4.0 中,Spark 上的 Pandas API 移除了 DatatimeIndex.weekDatatimeIndex.weekofyear,请改用 DatetimeIndex.isocalendar().week

  • 在 Spark 4.0 中,Spark 上的 Pandas API 移除了 Series.dt.weekSeries.dt.weekofyear,请改用 Series.dt.isocalendar().week

  • 在 Spark 4.0 中,当对十进制类型对象应用 astype 时,Spark 上的 Pandas API 中现有的缺失值更改为 True 而非 False

  • 在 Spark 4.0 中,Spark 上的 Pandas API 移除了 pyspark.testing.assertPandasOnSparkEqual,请改用 pyspark.pandas.testing.assert_frame_equal

  • 在 Spark 4.0 中,Spark 上的 Pandas API 弃用了别名 Y, M, H, T, S,请分别改用 YE, ME, h, min, s

  • 在 Spark 4.0 中,Map 列的模式通过合并 Map 中所有对的模式来推断。若要恢复仅从第一个非空对推断模式的旧行为,可以将 spark.sql.pyspark.legacy.inferMapTypeFromFirstPair.enabled 设置为 true

  • 在 Spark 4.0 中,compute.ops_on_diff_frames 默认开启。若要恢复之前的行为,请将 compute.ops_on_diff_frames 设置为 false

  • 在 Spark 4.0 中,DataFrame.collect 中的 YearMonthIntervalType 数据类型不再返回底层整数。若要恢复之前的行为,请将 PYSPARK_YM_INTERVAL_LEGACY 环境变量设置为 1

  • 在 Spark 4.0 中,函数以外的项目(如 DataFrame, Column, StructType)已从通配符导入 from pyspark.sql.functions import * 中移除,您应该从相应的模块中导入这些项目(例如 from pyspark.sql import DataFrame, Column, from pyspark.sql.types import StructType)。

  • 在 Spark 4.0 中,如果底层的 Spark 启用了 ANSI 模式(默认启用),Spark 上的 pandas API 将抛出异常,因为它无法在 ANSI 模式下正常工作。要使其工作,您需要通过将 spark.sql.ansi.enabled 设置为 false 来显式禁用 ANSI 模式。或者,您可以将 pandas-on-spark 选项 compute.fail_on_ansi_mode 设置为 False 以强制其工作,尽管这可能会导致意外行为。

从 PySpark 3.3 升级到 3.4#

  • 在 Spark 3.4 中,Array 列的模式通过合并数组中所有元素的模式来推断。若要恢复仅从第一个元素推断模式的旧行为,可以将 spark.sql.pyspark.legacy.inferArrayTypeFromFirstElement.enabled 设置为 true

  • 在 Spark 3.4 中,如果 Pandas on Spark API Groupby.applyfunc 参数返回类型未指定且 compute.shortcut_limit 设置为 0,采样行数将设置为 2(确保采样行数始终 >= 2),以确保模式推断准确。

  • 在 Spark 3.4 中,如果 Pandas on Spark API Index.insert 越界,将引发 IndexError,提示 index {} is out of bounds for axis 0 with size {},以遵循 pandas 1.4 的行为。

  • 在 Spark 3.4 中,Pandas on Spark API Series.mode 将保留 Series 名称,以遵循 pandas 1.4 的行为。

  • 在 Spark 3.4 中,Pandas on Spark API Index.__setitem__ 将首先检查 value 类型是否为 Column 类型,以避免在 is_list_like 中引发意外的 ValueError

  • 在 Spark 3.4 中,Pandas on Spark API astype('category') 也会根据原始数据 dtype 刷新 categories.dtype,以遵循 pandas 1.4 的行为。

  • 在 Spark 3.4 中,Pandas on Spark API 在 GroupBy.headGroupBy.tail 中支持分组位置索引,以遵循 pandas 1.4 的行为。负数参数现在可以正确工作,并产生相对于每个组末尾和开头的范围。以前,负数参数会返回空帧。

  • 在 Spark 3.4 中,Pandas on Spark 中 groupby.apply 的推断模式过程将首先推断 pandas 类型,以尽可能确保 pandas dtype 的准确性。

  • 在 Spark 3.4 中,Series.concat 的 sort 参数将被尊重,以遵循 pandas 1.4 的行为。

  • 在 Spark 3.4 中,DataFrame.__setitem__ 将进行复制并替换预先存在的数组,这些数组将不会被覆盖,以遵循 pandas 1.4 的行为。

  • 在 Spark 3.4 中,SparkSession.sql 和 Pandas on Spark API sql 获得了新参数 args,该参数提供命名参数与其 SQL 字面量的绑定。

  • 在 Spark 3.4 中,Pandas API on Spark 遵循 pandas 2.0,并且根据 pandas 2.0 中的更改,一些 API 在 Spark 3.4 中已被弃用或移除。详情请参考 [pandas 发布说明](https://pandas.ac.cn/docs/dev/whatsnew/)。

  • 在 Spark 3.4 中,移除了 collections.namedtuple 的自定义猴子补丁,并默认使用 cloudpickle。若要恢复任何相关 collections.namedtuple 序列化问题的先前行为,请将 PYSPARK_ENABLE_NAMEDTUPLE_PATCH 环境变量设置为 1

从 PySpark 3.2 升级到 3.3#

  • 在 Spark 3.3 中,pyspark.pandas.sql 方法遵循 [标准 Python 字符串格式化程序](https://docs.pythonlang.cn/3/library/string.html#format-string-syntax)。若要恢复之前的行为,请将 PYSPARK_PANDAS_SQL_LEGACY 环境变量设置为 1

  • 在 Spark 3.3 中,Spark DataFrame 上 pandas API 的 drop 方法支持按 index 删除行,并默认设置为按索引删除而不是按列删除。

  • 在 Spark 3.3 中,PySpark 升级了 Pandas 版本,新的最低要求版本从 0.23.2 变为 1.0.5。

  • 在 Spark 3.3 中,SQL DataTypes 的 repr 返回值已更改,以便在传递给 eval 时产生具有相同值的对象。

从 PySpark 3.1 升级到 3.2#

  • 在 Spark 3.2 中,来自 sql, ml, spark_on_pandas 模块的 PySpark 方法在应用于不适当类型的参数时会引发 TypeError 而不是 ValueError

  • 在 Spark 3.2 中,默认简化了 Python UDF、pandas UDF 和 pandas 函数 API 的回溯信息,不再包含来自内部 Python 工作线程的回溯。在 Spark 3.1 或更早版本中,会打印来自 Python 工作线程的回溯。若要恢复 Spark 3.2 之前的行为,可以将 spark.sql.execution.pyspark.udf.simplifiedTraceback.enabled 设置为 false

  • 在 Spark 3.2 中,默认启用了固定线程模式,将每个 Python 线程映射到相应的 JVM 线程。以前,一个 JVM 线程可以被多个 Python 线程重用,导致一个 JVM 线程本地变量被多个 Python 线程共享。此外,请注意现在建议对 Python 线程使用 pyspark.InheritableThreadpyspark.inheritable_thread_target,以便 Python 线程正确继承 JVM 线程中的可继承属性(如局部属性),并避免潜在的资源泄漏问题。若要恢复 Spark 3.2 之前的行为,可以将 PYSPARK_PIN_THREAD 环境变量设置为 false

从 PySpark 2.4 升级到 3.0#

  • 在 Spark 3.0 中,PySpark 要求 pandas 版本为 0.23.2 或更高版本,才能使用与 pandas 相关的功能,例如 toPandas、从 pandas DataFrame 创建 createDataFrame 等。

  • 在 Spark 3.0 中,PySpark 要求 PyArrow 版本为 0.12.1 或更高版本,才能使用与 PyArrow 相关的功能,例如 pandas_udftoPandas 以及设置了 “spark.sql.execution.arrow.enabled=true” 的 createDataFrame 等。

  • 在 PySpark 中,使用 SparkSession.builder.getOrCreate() 创建 SparkSession 时,如果已经存在 SparkContext,构建器以前会尝试用指定给构建器的配置来更新现有 SparkContextSparkConf。但由于 SparkContext 是由所有 SparkSession 共享的,我们不应该更新它们。在 3.0 中,构建器不再更新配置。这与 2.3 及更高版本中的 Java/Scala API 行为相同。如果您想更新它们,需要在创建 SparkSession 之前进行更新。

  • 在 PySpark 中,当启用了 Arrow 优化时,如果 Arrow 版本高于 0.11.0,Arrow 可以在序列化期间将 pandas.Series 转换为 Arrow 数组时执行安全类型转换。当检测到不安全类型转换(如溢出)时,Arrow 会引发错误。您可以通过设置 spark.sql.execution.pandas.convertToArrowArraySafely 为 true 来启用它。默认设置为 false。PySpark 对 Arrow 版本的行为如下图所示:

    PyArrow 版本

    整数溢出

    浮点数截断

    0.11.0 及以下

    引发错误

    静默允许

    > 0.11.0, arrowSafeTypeConversion=false

    静默溢出

    静默允许

    > 0.11.0, arrowSafeTypeConversion=true

    引发错误

    引发错误

  • 在 Spark 3.0 中,PySpark 中的 createDataFrame(..., verifySchema=True) 也会验证 LongType。以前,LongType 未被验证,在值溢出的情况下导致返回 None。若要恢复此行为,可以将 verifySchema 设置为 False 以禁用验证。

  • 从 Spark 3.0 开始,对于 Python 3.6 及以上版本,使用命名参数构造 Row 时,字段名不再按字母顺序排序,字段顺序将与输入顺序一致。要像 Spark 2.4 那样默认启用字段排序,请为执行器和驱动程序设置环境变量 PYSPARK_ROW_FIELD_SORTING_ENABLED 为 true - 此环境变量必须在所有执行器和驱动程序上保持一致;否则,可能会导致失败或错误的结果。对于低于 3.6 的 Python 版本,字段名将始终按字母顺序排序。

  • 在 Spark 3.0 中,pyspark.ml.param.shared.Has* 混合类不再提供任何 set*(self, value) 设置器方法,请改用相应的 self.set(self.*, value)。详情请参阅 SPARK-29093

从 PySpark 2.3 升级到 2.4#

  • 在 PySpark 中,当启用 Arrow 优化时,以前 toPandas 在无法使用 Arrow 优化时会失败,而从 Pandas DataFrame 创建的 createDataFrame 允许回退到非优化方式。现在,toPandas 和从 Pandas DataFrame 创建的 createDataFrame 默认都允许回退,这可以通过 spark.sql.execution.arrow.fallback.enabled 进行切换。

从 PySpark 2.3.0 升级到 2.3.1 及以上#

  • 从 2.3.1 版本开始,包括 pandas_udf 以及设置了 spark.sql.execution.arrow.enabledTruetoPandas()/createDataFrame() 在内的 Arrow 功能已被标记为实验性。这些功能仍在不断演进,目前不建议在生产环境中使用。

从 PySpark 2.2 升级到 2.3#

  • 在 PySpark 中,现在如果您想使用与 Pandas 相关的功能(如 toPandas、从 Pandas DataFrame 创建 createDataFrame 等),则需要 Pandas 0.19.2 或更高版本。

  • 在 PySpark 中,与 Pandas 相关功能的时间戳值行为已更改,以尊重会话时区。如果您想使用旧行为,需要将配置 spark.sql.execution.pandas.respectSessionTimeZone 设置为 False。详情请参阅 SPARK-22395

  • 在 PySpark 中,na.fill()fillna 现在也接受布尔值,并将空值替换为布尔值。在之前的 Spark 版本中,PySpark 会忽略它并返回原始的 Dataset/DataFrame。

  • 在 PySpark 中,当 to_replace 不是字典时,df.replace 不允许省略值。以前,在其他情况下可以省略值并默认为 None,这违反直觉且容易出错。

从 PySpark 1.4 升级到 1.5#

  • Python 中字符串到列的解析现在支持使用点 (.) 来限定列或访问嵌套值。例如 df['table.column.nestedField']。但是,这意味着如果您的列名包含任何点,则必须现在使用反引号转义它们(例如 table.`column.with.dots`.nested)。

  • PySpark 中的 DataFrame.withColumn 方法支持添加新列或替换同名的现有列。

从 PySpark 1.0-1.2 升级到 1.3#

  • 在 Python 中使用 DataTypes 时,您需要构造它们(即 StringType()),而不是引用单例。