Skip to content

[SPARK-52215][PYTHON][CONNECT] Implement Scalar Arrow UDF - #50759

Closed
zhengruifeng wants to merge 16 commits into
apache:masterfrom
zhengruifeng:py_arrow_udf
Closed

zhengruifeng wants to merge 16 commits into
apache:masterfrom
zhengruifeng:py_arrow_udf

Conversation

@zhengruifeng

@zhengruifeng zhengruifeng commented Apr 30, 2025 •

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Implement Scalar Arrow UDF

Why are the changes needed?

Pandas UDFs (and Pandas Functions like MapInPandas) have a pandas <> arrow conversion, but:

  • This conversion is not stable, and gets broken from time to time
    -- The Arrow 13 upgrade, pandas UDFs with data/time types are all broken;
    -- Weird behavior when the dataset is empty
  • Pandas <> Arrow conversion is pretty expensive. Zero-copy is only possible in certain narrow cases, e.g. StringType is not supported;
  • The support of complex type is not good, e.g. to support StructType series, we needs to use pd.DataFrame as a workaround;

Arrow UDF is designed to resolve above issues.

Does this PR introduce any user-facing change?

No, this PR makes the underlying implementation, under pyspark.sql.pandas.functions which is not a public module.

So the new feature is not exposed to end users for now, we will need to decide the API later.

import pyarrow as pa

from pyspark.sql import functions as sf
from pyspark.sql.pandas.functions import arrow_udf      <- `pyspark.sql.pandas.functions` is not public

df = spark.range(10).withColumn("v", sf.col("id") + 1)


@arrow_udf("long")
def multiply_arrow_func(a: pa.Array, b: pa.Array) -> pa.Array:
    assert isinstance(a, pa.Array)
    assert isinstance(b, pa.Array)
    return pa.compute.multiply(a, b)


df.select("id", "v", multiply_arrow_func("id", "v").alias("m")).show()


+---+---+---+
| id|  v|  m|
+---+---+---+
|  0|  1|  0|
|  1|  2|  2|
|  2|  3|  6|
|  3|  4| 12|
|  4|  5| 20|
|  5|  6| 30|
|  6|  7| 42|
|  7|  8| 56|
|  8|  9| 72|
|  9| 10| 90|
+---+---+---+

How was this patch tested?

new tests

Was this patch authored or co-authored using generative AI tooling?

no

@zhengruifeng
zhengruifeng force-pushed the py_arrow_udf branch 2 times, most recently from c2c5e80 to de0ca44 Compare May 19, 2025 09:17
@zhengruifeng zhengruifeng changed the title [WIP][PYTHON][CONNECT] Introduce Scalar Arrow UDF [SPARK-52215][PYTHON][CONNECT] Implement Scalar Arrow UDF May 19, 2025
@zhengruifeng
zhengruifeng marked this pull request as ready for review May 19, 2025 09:23
@zhengruifeng

Copy link
Copy Markdown
Contributor Author

also cc @asl3 since this might be reused for removing pandas conversion in arrow-optimized UDF

@ueshin ueshin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise, LGTM.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: how about using a separate id group, like 250 and above, following the corresponding pandas UDF's eval type, like SQL_GROUPED_MAP_ARROW_UDF = 251?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: +1, or we have "SQL_ARROW_TABLE_UDF = 301", not sure which group is a better fit

@allisonwang-db allisonwang-db May 20, 2025 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about val SQL_SCALAR_ARROW_UDF = 250

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good!

Comment on lines 64 to 67

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be ArrowVariadicScalarToScalarFunction?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch!

@xinrong-meng

xinrong-meng commented May 19, 2025 •

Copy link
Copy Markdown
Member

Added py to the code in the PR description for better visualization :)

@zhengruifeng
zhengruifeng force-pushed the py_arrow_udf branch 3 times, most recently from 59e19bf to 199f64f Compare May 20, 2025 09:04
@zhengruifeng

Copy link
Copy Markdown
Contributor Author

thank you all, merged to master

@zhengruifeng
zhengruifeng deleted the py_arrow_udf branch May 21, 2025 02:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants