def transform(obj: FrameOrSeries, func: AggFuncType, axis: Axis, *args, **kwargs) -> FrameOrSeries: """ Transform a DataFrame or Series Parameters ---------- obj : DataFrame or Series Object to compute the transform on. func : string, function, list, or dictionary Function(s) to compute the transform with. axis : {0 or 'index', 1 or 'columns'} Axis along which the function is applied: * 0 or 'index': apply function to each column. * 1 or 'columns': apply function to each row. Returns ------- DataFrame or Series Result of applying ``func`` along the given axis of the Series or DataFrame. Raises ------ ValueError If the transform function fails or does not transform. """ is_series = obj.ndim == 1 if obj._get_axis_number(axis) == 1: assert not is_series return transform(obj.T, func, 0, *args, **kwargs).T if isinstance(func, list): if is_series: func = {com.get_callable_name(v) or v: v for v in func} else: func = {col: func for col in obj} if isinstance(func, dict): return transform_dict_like(obj, func, *args, **kwargs) # func is either str or callable try: result = transform_str_or_callable(obj, func, *args, **kwargs) except Exception: raise ValueError("Transform function failed") # Functions that transform may return empty Series/DataFrame # when the dtype is not appropriate if isinstance(result, (ABCSeries, ABCDataFrame)) and result.empty: raise ValueError("Transform function failed") if not isinstance(result, (ABCSeries, ABCDataFrame)) or not result.index.equals( obj.index): raise ValueError("Function did not transform") return result
def transform(obj: FrameOrSeries, func: AggFuncType, axis: Axis, *args, **kwargs) -> FrameOrSeries: """ Transform a DataFrame or Series Parameters ---------- obj : DataFrame or Series Object to compute the transform on. func : string, function, list, or dictionary Function(s) to compute the transform with. axis : {0 or 'index', 1 or 'columns'} Axis along which the function is applied: * 0 or 'index': apply function to each column. * 1 or 'columns': apply function to each row. Returns ------- DataFrame or Series Result of applying ``func`` along the given axis of the Series or DataFrame. Raises ------ ValueError If the transform function fails or does not transform. """ from pandas.core.reshape.concat import concat is_series = obj.ndim == 1 if obj._get_axis_number(axis) == 1: assert not is_series return transform(obj.T, func, 0, *args, **kwargs).T if isinstance(func, list): if is_series: func = {com.get_callable_name(v) or v: v for v in func} else: func = {col: func for col in obj} if isinstance(func, dict): if not is_series: cols = sorted(set(func.keys()) - set(obj.columns)) if len(cols) > 0: raise SpecificationError(f"Column(s) {cols} do not exist") if any(isinstance(v, dict) for v in func.values()): # GH 15931 - deprecation of renaming keys raise SpecificationError("nested renamer is not supported") results = {} for name, how in func.items(): colg = obj._gotitem(name, ndim=1) try: results[name] = transform(colg, how, 0, *args, **kwargs) except Exception as e: if str(e) == "Function did not transform": raise e # combine results if len(results) == 0: raise ValueError("Transform function failed") return concat(results, axis=1) # func is either str or callable try: if isinstance(func, str): result = obj._try_aggregate_string_function(func, *args, **kwargs) else: f = obj._get_cython_func(func) if f and not args and not kwargs: result = getattr(obj, f)() else: try: result = obj.apply(func, args=args, **kwargs) except Exception: result = func(obj, *args, **kwargs) except Exception: raise ValueError("Transform function failed") # Functions that transform may return empty Series/DataFrame # when the dtype is not appropriate if isinstance(result, (ABCSeries, ABCDataFrame)) and result.empty: raise ValueError("Transform function failed") if not isinstance(result, (ABCSeries, ABCDataFrame)) or not result.index.equals( obj.index): raise ValueError("Function did not transform") return result