Skip to content

Commit 02a970a

Browse files
fix precedence
1 parent 91f65dc commit 02a970a

1 file changed

Lines changed: 36 additions & 30 deletions

File tree

packages/bigframes/bigframes/series.py

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,41 +2065,32 @@ def apply(
20652065
" are supported."
20662066
)
20672067

2068-
from bigframes._config import options
20692068

2069+
# Highest priority: try to map directly to an operator, for eg numpy
2070+
# ufuncs, or simple arithmetic/logic operators.
20702071
bf_op = python_ops.python_callable_to_op(func)
20712072
if bf_op and isinstance(bf_op, ops.UnaryOp):
20722073
return self._apply_unary_op(bf_op)
20732074

2074-
if isinstance(func, bigframes.functions.Udf) or (
2075-
options.experiments.enable_python_transpiler and callable(func)
2076-
):
2077-
# We are working with bigquery function at this point
2078-
result_series = self._apply_callable_expr(ops.func_to_expr(func), args)
2079-
# TODO(jialuo): Investigate why `_apply_nary_op` drops the series
2080-
# `name`. Manually reassigning it here as a temporary fix.
2081-
result_series.name = self.name
2082-
2083-
return result_series
2084-
2085-
# It is neither a remote function nor a managed function.
2086-
# Then it must be a vectorized function that applies to the Series
2087-
# as a whole.
2088-
if by_row:
2089-
raise ValueError(
2090-
"You have passed a function as-is. If your intention is to "
2091-
"apply this function in a vectorized way (i.e. to the "
2092-
"entire Series as a whole, and you are sure that it "
2093-
"performs only the operations that are implemented for a "
2094-
"Series (e.g. a chain of arithmetic/logical operations, "
2095-
"such as `def foo(s): return s % 2 == 1`), please also "
2096-
"specify `by_row=False`. If your function contains "
2097-
"arbitrary code, it can only be applied to every element "
2098-
"in the Series individually, in which case you must "
2099-
"convert it to a BigFrames BigQuery function using "
2100-
"`bigframes.pandas.udf`, "
2101-
"or `bigframes.pandas.remote_function` before passing."
2102-
)
2075+
# "compat": try by row, and then fall back to passing whole series if that fails
2076+
if by_row:
2077+
try:
2078+
return self._apply_by_row(func)
2079+
except Exception as ex:
2080+
raise ValueError(
2081+
"You have passed a function as-is. If your intention is to "
2082+
"apply this function in a vectorized way (i.e. to the "
2083+
"entire Series as a whole, and you are sure that it "
2084+
"performs only the operations that are implemented for a "
2085+
"Series (e.g. a chain of arithmetic/logical operations, "
2086+
"such as `def foo(s): return s % 2 == 1`), please also "
2087+
"specify `by_row=False`. If your function contains "
2088+
"arbitrary code, it can only be applied to every element "
2089+
"in the Series individually, in which case you must "
2090+
"convert it to a BigFrames BigQuery function using "
2091+
"`bigframes.pandas.udf`, "
2092+
"or `bigframes.pandas.remote_function` before passing."
2093+
)
21032094

21042095
try:
21052096
return func(self) # type: ignore
@@ -2111,6 +2102,21 @@ def apply(
21112102
ex.message += f"\n{_bigquery_function_recommendation_message}"
21122103
raise
21132104

2105+
def _apply_by_row(self, func: typing.Callable, args: typing.Tuple = ()) -> Series:
2106+
from bigframes._config import options
2107+
2108+
if isinstance(func, bigframes.functions.Udf) or (
2109+
options.experiments.enable_python_transpiler and callable(func)
2110+
):
2111+
# We are working with bigquery function at this point
2112+
result_series = self._apply_callable_expr(ops.func_to_expr(func), args)
2113+
# TODO(jialuo): Investigate why `_apply_nary_op` drops the series
2114+
# `name`. Manually reassigning it here as a temporary fix.
2115+
result_series.name = self.name
2116+
2117+
return result_series
2118+
raise ValueError(f"Cannot apply function {func} to Series {self}")
2119+
21142120
def combine(
21152121
self,
21162122
other,

0 commit comments

Comments
 (0)