# Buggy code
def apply(
    self,
    func,
    axis=0,
    broadcast=None,
    raw=False,
    reduce=None,
    result_type=None,
    convert_dtype=True,
    args=(),
    **kwds,
):
    """Apply a function along input axis of DataFrame.

    Args:
        func: The function to apply
        axis: The axis over which to apply the func.
        broadcast: Whether or not to broadcast.
        raw: Whether or not to convert to a Series.
        reduce: Whether or not to try to apply reduction procedures.

    Returns:
        Series or DataFrame, depending on func.
    """
    axis = self._get_axis_number(axis)
    ErrorMessage.non_verified_udf()
    if isinstance(func, str):
        if axis == 1:
            kwds["axis"] = axis
        result = self._string_function(func, *args, **kwds)
        # Sometimes we can return a scalar here
        if isinstance(result, BasePandasDataset):
            return result._query_compiler
        return result
    elif isinstance(func, dict):
        if axis == 1:
            raise TypeError(
                "(\"'dict' object is not callable\", 'occurred at index {0}'".format(
                    self.index[0]
                )
            )
        if len(self.columns) != len(set(self.columns)):
            warnings.warn(
                "duplicate column names not supported with apply().",
                FutureWarning,
                stacklevel=2,
            )
    elif not callable(func) and not is_list_like(func):
        raise TypeError("{} object is not callable".format(type(func)))
    query_compiler = self._query_compiler.apply(func, axis, *args, **kwds)
    return query_compiler


# Traceback (TypeError)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-69-936ab004d2a8> in <module>
2     df = pd.read_csv(file_path)
3     data_per_user = generate_data_per_user_dicts()
----> 4     df.apply(extract_data_per_user, axis=1, args=(data_per_user,))
5
6     file_name = file_path.split("/")[-1].strip(".csv")

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\pandas\dataframe.py in apply(self, func, axis, broadcast, raw, reduce, result_type, convert_dtype, args, **kwds)
279             convert_dtype=convert_dtype,
280             args=args,
--> 281             **kwds
282         )
283         if not isinstance(query_compiler, type(self._query_compiler)):

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\pandas\base.py in apply(self, func, axis, broadcast, raw, reduce, result_type, convert_dtype, args, **kwds)
561         elif not callable(func) and not is_list_like(func):
562             raise TypeError("{} object is not callable".format(type(func)))
--> 563         query_compiler = self._query_compiler.apply(func, axis, *args, **kwds)
564         return query_compiler
565

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\backends\pandas\query_compiler.py in apply(self, func, axis, *args, **kwargs)
1034         """
1035         if callable(func):
-> 1036             return self._callable_func(func, axis, *args, **kwargs)
1037         elif isinstance(func, dict):
1038             return self._dict_func(func, axis, *args, **kwargs)

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\backends\pandas\query_compiler.py in _callable_func(self, func, axis, *args, **kwargs)
1111         else:
1112             new_modin_frame = self._modin_frame._apply_full_axis(
-> 1113                 axis, lambda df: df.apply(func, axis=axis, *args, **kwargs)
1114             )
1115         return self.__constructor__(new_modin_frame)

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\engines\base\frame\data.py in _apply_full_axis(self, axis, func, new_index, new_columns, dtypes)
847         if new_columns is None:
848             new_columns = self._frame_mgr_cls.get_indices(
--> 849                 1, new_partitions, lambda df: df.columns
850             )
851         if new_index is None:

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\engines\dask\pandas_on_dask_futures\frame\partition_manager.py in get_indices(cls, axis, partitions, index_func)
53                 else []
54             )
---> 55         new_idx = client.gather(new_idx)
56         return new_idx[0].append(new_idx[1:]) if len(new_idx) else new_idx

~\AppData\Local\Continuum\anaconda3\lib\site-packages\distributed\client.py in gather(self, futures, errors, direct, asynchronous)
1871                 direct=direct,
1872                 local_worker=local_worker,
-> 1873                 asynchronous=asynchronous,
1874             )
1875

~\AppData\Local\Continuum\anaconda3\lib\site-packages\distributed\client.py in sync(self, func, asynchronous, callback_timeout, *args, **kwargs)
766         else:
767             return sync(
--> 768                 self.loop, func, *args, callback_timeout=callback_timeout, **kwargs
769             )
770

~\AppData\Local\Continuum\anaconda3\lib\site-packages\distributed\utils.py in sync(loop, func, callback_timeout, *args, **kwargs)
332     if error[0]:
333         typ, exc, tb = error[0]
--> 334         raise exc.with_traceback(tb)
335     else:
336         return result[0]

~\AppData\Local\Continuum\anaconda3\lib\site-packages\distributed\utils.py in f()
316             if callback_timeout is not None:
317                 future = gen.with_timeout(timedelta(seconds=callback_timeout), future)
--> 318             result[0] = yield future
319         except Exception as exc:
320             error[0] = sys.exc_info()

~\AppData\Local\Continuum\anaconda3\lib\site-packages\tornado\gen.py in run(self)
727
728                     try:
--> 729                         value = future.result()
730                     except Exception:
731                         exc_info = sys.exc_info()

~\AppData\Local\Continuum\anaconda3\lib\site-packages\distributed\client.py in _gather(self, futures, errors, direct, local_worker)
1727                             exc = CancelledError(key)
1728                         else:
-> 1729                             raise exception.with_traceback(traceback)
1730                         raise exc
1731                     if errors == "skip":

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\engines\base\frame\axis_partition.py in deploy_axis_func()
187
188         dataframe = pandas.concat(list(partitions), axis=axis, copy=False)
--> 189         result = func(dataframe, **kwargs)
190         if isinstance(result, pandas.Series):
191             if num_splits == 1:

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\engines\base\frame\data.py in _map_reduce_func()
652
653         def _map_reduce_func(df):
--> 654             series_result = func(df)
655             if axis == 0 and isinstance(series_result, pandas.Series):
656                 # In the case of axis=0, we need to keep the shape of the data

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\backends\pandas\query_compiler.py in <lambda>()
1111         else:
1112             new_modin_frame = self._modin_frame._apply_full_axis(
-> 1113                 axis, lambda df: df.apply(func, axis=axis, *args, **kwargs)
1114             )
1115         return self.__constructor__(new_modin_frame)

TypeError: apply() got multiple values for argument 'axis'

# Fixed code
def apply(
    self,
    func,
    axis=0,
    broadcast=None,
    raw=False,
    reduce=None,
    result_type=None,
    convert_dtype=True,
    args=(),
    **kwds,
):
    """Apply a function along input axis of DataFrame.

    Args:
        func: The function to apply
        axis: The axis over which to apply the func.
        broadcast: Whether or not to broadcast.
        raw: Whether or not to convert to a Series.
        reduce: Whether or not to try to apply reduction procedures.

    Returns:
        Series or DataFrame, depending on func.
    """
    axis = self._get_axis_number(axis)
    ErrorMessage.non_verified_udf()
    if isinstance(func, str):
        if axis == 1:
            kwds["axis"] = axis
        result = self._string_function(func, *args, **kwds)
        # Sometimes we can return a scalar here
        if isinstance(result, BasePandasDataset):
            return result._query_compiler
        return result
    elif isinstance(func, dict):
        if axis == 1:
            raise TypeError(
                "(\"'dict' object is not callable\", 'occurred at index {0}'".format(
                    self.index[0]
                )
            )
        if len(self.columns) != len(set(self.columns)):
            warnings.warn(
                "duplicate column names not supported with apply().",
                FutureWarning,
                stacklevel=2,
            )
    elif not callable(func) and not is_list_like(func):
        raise TypeError("{} object is not callable".format(type(func)))
    query_compiler = self._query_compiler.apply(func, axis, args=args, **kwds)
    return query_compiler