def nsmallest(self, n: int, columns: Union[(Name, List[Name])], keep: str='first') -> 'DataFrame':
    '\n        Return the first `n` rows ordered by `columns` in ascending order.\n\n        Return the first `n` rows with the smallest values in `columns`, in\n        ascending order. The columns that are not specified are returned as\n        well, but not used for ordering.\n\n        This method is equivalent to ``df.sort_values(columns, ascending=True).head(n)``,\n        but more performant. In pandas-on-Spark, thanks to Spark\'s lazy execution and query\n        optimizer, the two would have same performance.\n\n        Parameters\n        ----------\n        n : int\n            Number of items to retrieve.\n        columns : list or str\n            Column name or names to order by.\n        keep : {\'first\', \'last\'}, default \'first\'. \'all\' is not implemented yet.\n            Determines which duplicates (if any) to keep.\n            - ``first`` : Keep the first occurrence.\n            - ``last`` : Keep the last occurrence.\n\n        Returns\n        -------\n        DataFrame\n\n        See Also\n        --------\n        DataFrame.nlargest : Return the first `n` rows ordered by `columns` in\n            descending order.\n        DataFrame.sort_values : Sort DataFrame by the values.\n        DataFrame.head : Return the first `n` rows without re-ordering.\n\n        Examples\n        --------\n        >>> df = ps.DataFrame({\'X\': [1, 2, 3, 5, 6, 7, np.nan],\n        ...                    \'Y\': [6, 7, 8, 9, 10, 11, 12]})\n        >>> df\n             X   Y\n        0  1.0   6\n        1  2.0   7\n        2  3.0   8\n        3  5.0   9\n        4  6.0  10\n        5  7.0  11\n        6  NaN  12\n\n        In the following example, we will use ``nsmallest`` to select the\n        three rows having the smallest values in column "X".\n\n        >>> df.nsmallest(n=3, columns=\'X\') # doctest: +NORMALIZE_WHITESPACE\n             X   Y\n        0  1.0   6\n        1  2.0   7\n        2  3.0   8\n\n        To order by the smallest values in column "Y" and then "X", we can\n        specify multiple columns like in the next example.\n\n        >>> df.nsmallest(n=3, columns=[\'Y\', \'X\']) # doctest: +NORMALIZE_WHITESPACE\n             X   Y\n        0  1.0   6\n        1  2.0   7\n        2  3.0   8\n\n        The examples below show how ties are resolved, which is decided by `keep`.\n\n        >>> tied_df = ps.DataFrame({\'X\': [1, 1, 2, 2, 3]}, index=[\'a\', \'b\', \'c\', \'d\', \'e\'])\n        >>> tied_df\n           X\n        a  1\n        b  1\n        c  2\n        d  2\n        e  3\n\n        When using keep=\'first\' (by default), ties are resolved in order:\n\n        >>> tied_df.nsmallest(3, \'X\')\n           X\n        a  1\n        b  1\n        c  2\n\n        >>> tied_df.nsmallest(3, \'X\', keep=\'first\')\n           X\n        a  1\n        b  1\n        c  2\n\n        When using keep=\'last\', ties are resolved in reverse order:\n\n        >>> tied_df.nsmallest(3, \'X\', keep=\'last\')\n           X\n        b  1\n        a  1\n        d  2\n        '
    by_scols = self._prepare_sort_by_scols(columns)
    return self._sort(by=by_scols, ascending=True, na_position='last', keep=keep).head(n=n)
Return the first `n` rows ordered by `columns` in ascending order.

Return the first `n` rows with the smallest values in `columns`, in
ascending order. The columns that are not specified are returned as
well, but not used for ordering.

This method is equivalent to ``df.sort_values(columns, ascending=True).head(n)``,
but more performant. In pandas-on-Spark, thanks to Spark's lazy execution and query
optimizer, the two would have same performance.

Parameters
----------
n : int
    Number of items to retrieve.
columns : list or str
    Column name or names to order by.
keep : {'first', 'last'}, default 'first'. 'all' is not implemented yet.
    Determines which duplicates (if any) to keep.
    - ``first`` : Keep the first occurrence.
    - ``last`` : Keep the last occurrence.

Returns
-------
DataFrame

See Also
--------
DataFrame.nlargest : Return the first `n` rows ordered by `columns` in
    descending order.
DataFrame.sort_values : Sort DataFrame by the values.
DataFrame.head : Return the first `n` rows without re-ordering.

Examples
--------
>>> df = ps.DataFrame({'X': [1, 2, 3, 5, 6, 7, np.nan],
...                    'Y': [6, 7, 8, 9, 10, 11, 12]})
>>> df
     X   Y
0  1.0   6
1  2.0   7
2  3.0   8
3  5.0   9
4  6.0  10
5  7.0  11
6  NaN  12

In the following example, we will use ``nsmallest`` to select the
three rows having the smallest values in column "X".

>>> df.nsmallest(n=3, columns='X') # doctest: +NORMALIZE_WHITESPACE
     X   Y
0  1.0   6
1  2.0   7
2  3.0   8

To order by the smallest values in column "Y" and then "X", we can
specify multiple columns like in the next example.

>>> df.nsmallest(n=3, columns=['Y', 'X']) # doctest: +NORMALIZE_WHITESPACE
     X   Y
0  1.0   6
1  2.0   7
2  3.0   8

The examples below show how ties are resolved, which is decided by `keep`.

>>> tied_df = ps.DataFrame({'X': [1, 1, 2, 2, 3]}, index=['a', 'b', 'c', 'd', 'e'])
>>> tied_df
   X
a  1
b  1
c  2
d  2
e  3

When using keep='first' (by default), ties are resolved in order:

>>> tied_df.nsmallest(3, 'X')
   X
a  1
b  1
c  2

>>> tied_df.nsmallest(3, 'X', keep='first')
   X
a  1
b  1
c  2

When using keep='last', ties are resolved in reverse order:

>>> tied_df.nsmallest(3, 'X', keep='last')
   X
b  1
a  1
d  2
def nsmallest(self, n: int, columns: Union[(Name, List[Name])], keep: str='first') -> 'DataFrame':
    '\n        Return the first `n` rows ordered by `columns` in ascending order.\n\n        Return the first `n` rows with the smallest values in `columns`, in\n        ascending order. The columns that are not specified are returned as\n        well, but not used for ordering.\n\n        This method is equivalent to ``df.sort_values(columns, ascending=True).head(n)``,\n        but more performant. In pandas-on-Spark, thanks to Spark\'s lazy execution and query\n        optimizer, the two would have same performance.\n\n        Parameters\n        ----------\n        n : int\n            Number of items to retrieve.\n        columns : list or str\n            Column name or names to order by.\n        keep : {\'first\', \'last\'}, default \'first\'. \'all\' is not implemented yet.\n            Determines which duplicates (if any) to keep.\n            - ``first`` : Keep the first occurrence.\n            - ``last`` : Keep the last occurrence.\n\n        Returns\n        -------\n        DataFrame\n\n        See Also\n        --------\n        DataFrame.nlargest : Return the first `n` rows ordered by `columns` in\n            descending order.\n        DataFrame.sort_values : Sort DataFrame by the values.\n        DataFrame.head : Return the first `n` rows without re-ordering.\n\n        Examples\n        --------\n        >>> df = ps.DataFrame({\'X\': [1, 2, 3, 5, 6, 7, np.nan],\n        ...                    \'Y\': [6, 7, 8, 9, 10, 11, 12]})\n        >>> df\n             X   Y\n        0  1.0   6\n        1  2.0   7\n        2  3.0   8\n        3  5.0   9\n        4  6.0  10\n        5  7.0  11\n        6  NaN  12\n\n        In the following example, we will use ``nsmallest`` to select the\n        three rows having the smallest values in column "X".\n\n        >>> df.nsmallest(n=3, columns=\'X\') # doctest: +NORMALIZE_WHITESPACE\n             X   Y\n        0  1.0   6\n        1  2.0   7\n        2  3.0   8\n\n        To order by the smallest values in column "Y" and then "X", we can\n        specify multiple columns like in the next example.\n\n        >>> df.nsmallest(n=3, columns=[\'Y\', \'X\']) # doctest: +NORMALIZE_WHITESPACE\n             X   Y\n        0  1.0   6\n        1  2.0   7\n        2  3.0   8\n\n        The examples below show how ties are resolved, which is decided by `keep`.\n\n        >>> tied_df = ps.DataFrame({\'X\': [1, 1, 2, 2, 3]}, index=[\'a\', \'b\', \'c\', \'d\', \'e\'])\n        >>> tied_df\n           X\n        a  1\n        b  1\n        c  2\n        d  2\n        e  3\n\n        When using keep=\'first\' (by default), ties are resolved in order:\n\n        >>> tied_df.nsmallest(3, \'X\')\n           X\n        a  1\n        b  1\n        c  2\n\n        >>> tied_df.nsmallest(3, \'X\', keep=\'first\')\n           X\n        a  1\n        b  1\n        c  2\n\n        When using keep=\'last\', ties are resolved in reverse order:\n\n        >>> tied_df.nsmallest(3, \'X\', keep=\'last\')\n           X\n        b  1\n        a  1\n        d  2\n        '
    by_scols = self._prepare_sort_by_scols(columns)
    return self._sort(by=by_scols, ascending=True, na_position='last', keep=keep).head(n=n)