# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Additional Spark functions used in pandas-on-Spark. """ from typing import Union from pyspark import SparkContext import pyspark.sql.functions as F from pyspark.sql.column import Column # For supporting Spark Connect from pyspark.sql.utils import is_remote def product(col: Column, dropna: bool) -> Column: if is_remote(): from pyspark.sql.connect.functions import _invoke_function_over_columns, lit return _invoke_function_over_columns( # type: ignore[return-value] "pandas_product", col, # type: ignore[arg-type] lit(dropna), ) else: sc = SparkContext._active_spark_context return Column(sc._jvm.PythonSQLUtils.pandasProduct(col._jc, dropna)) def stddev(col: Column, ddof: int) -> Column: if is_remote(): from pyspark.sql.connect.functions import _invoke_function_over_columns, lit return _invoke_function_over_columns( # type: ignore[return-value] "pandas_stddev", col, # type: ignore[arg-type] lit(ddof), ) else: sc = SparkContext._active_spark_context return Column(sc._jvm.PythonSQLUtils.pandasStddev(col._jc, ddof)) def var(col: Column, ddof: int) -> Column: if is_remote(): from pyspark.sql.connect.functions import _invoke_function_over_columns, lit return _invoke_function_over_columns( # type: ignore[return-value] "pandas_var", col, # type: ignore[arg-type] lit(ddof), ) else: sc = SparkContext._active_spark_context return Column(sc._jvm.PythonSQLUtils.pandasVariance(col._jc, ddof)) def skew(col: Column) -> Column: if is_remote(): from pyspark.sql.connect.functions import _invoke_function_over_columns return _invoke_function_over_columns( # type: ignore[return-value] "pandas_skew", col, # type: ignore[arg-type] ) else: sc = SparkContext._active_spark_context return Column(sc._jvm.PythonSQLUtils.pandasSkewness(col._jc)) def kurt(col: Column) -> Column: if is_remote(): from pyspark.sql.connect.functions import _invoke_function_over_columns return _invoke_function_over_columns( # type: ignore[return-value] "pandas_kurt", col, # type: ignore[arg-type] ) else: sc = SparkContext._active_spark_context return Column(sc._jvm.PythonSQLUtils.pandasKurtosis(col._jc)) def mode(col: Column, dropna: bool) -> Column: if is_remote(): from pyspark.sql.connect.functions import _invoke_function_over_columns, lit return _invoke_function_over_columns( # type: ignore[return-value] "pandas_mode", col, # type: ignore[arg-type] lit(dropna), ) else: sc = SparkContext._active_spark_context return Column(sc._jvm.PythonSQLUtils.pandasMode(col._jc, dropna)) def covar(col1: Column, col2: Column, ddof: int) -> Column: if is_remote(): from pyspark.sql.connect.functions import _invoke_function_over_columns, lit return _invoke_function_over_columns( # type: ignore[return-value] "pandas_covar", col1, # type: ignore[arg-type] col2, # type: ignore[arg-type] lit(ddof), ) else: sc = SparkContext._active_spark_context return Column(sc._jvm.PythonSQLUtils.pandasCovar(col1._jc, col2._jc, ddof)) def repeat(col: Column, n: Union[int, Column]) -> Column: """ Repeats a string column n times, and returns it as a new string column. """ _n = F.lit(n) if isinstance(n, int) else n return F.call_udf("repeat", col, _n) def ewm(col: Column, alpha: float, ignore_na: bool) -> Column: if is_remote(): from pyspark.sql.connect.functions import _invoke_function_over_columns, lit return _invoke_function_over_columns( # type: ignore[return-value] "ewm", col, # type: ignore[arg-type] lit(alpha), lit(ignore_na), ) else: sc = SparkContext._active_spark_context return Column(sc._jvm.PythonSQLUtils.ewm(col._jc, alpha, ignore_na)) def last_non_null(col: Column) -> Column: if is_remote(): from pyspark.sql.connect.functions import _invoke_function_over_columns return _invoke_function_over_columns( # type: ignore[return-value] "last_non_null", col, # type: ignore[arg-type] ) else: sc = SparkContext._active_spark_context return Column(sc._jvm.PythonSQLUtils.lastNonNull(col._jc)) def null_index(col: Column) -> Column: if is_remote(): from pyspark.sql.connect.functions import _invoke_function_over_columns return _invoke_function_over_columns( # type: ignore[return-value] "null_index", col, # type: ignore[arg-type] ) else: sc = SparkContext._active_spark_context return Column(sc._jvm.PythonSQLUtils.nullIndex(col._jc)) def timestampdiff(unit: str, start: Column, end: Column) -> Column: if is_remote(): from pyspark.sql.connect.functions import _invoke_function_over_columns, lit return _invoke_function_over_columns( # type: ignore[return-value] "timestampdiff", lit(unit), start, # type: ignore[arg-type] end, # type: ignore[arg-type] ) else: sc = SparkContext._active_spark_context return Column(sc._jvm.PythonSQLUtils.timestampDiff(unit, start._jc, end._jc))