Repository: pyjanitor-devs/pyjanitor

Issue:
All the code blocks in the docs are borked.
Title.


Discussion:
Let me try examining the readthedocs logs.
Figured out what's going wrong. Docstrings were messed up somehow. Fixing right now. Unfortunately, there's no automated tool for this...
Enjoy that

Resolving patch:
diff --git a/janitor/finance.py b/janitor/finance.py
--- a/janitor/finance.py
+++ b/janitor/finance.py
@@ -63,7 +63,9 @@ def _convert_currency(
 ):
     """
     Currency conversion for Pandas DataFrame column.
+
     Helper function for `convert_currency` method.
+
     The API used is: https://exchangeratesapi.io/
     """
 
@@ -116,69 +118,72 @@ def convert_currency(
     make_new_column: bool = False,
 ):
     """
-        Converts a column from one currency to another, with an option to
-        convert based on historical exchange values.
-
-        :param df: A pandas dataframe.
-        :param colname: Name of the new column. Should be a string, in order
-            for the column name to be compatible with the Feather binary
-            format (this is a useful thing to have).
-        :param from_currency: The base currency to convert from.
-            May be any of: currency_set = {"AUD", "BGN", "BRL", "CAD", "CHF",
-            "CNY", "CZK", "DKK", "EUR", "GBP", "HKD", "HRK", "HUF", "IDR",
-            "ILS", "INR", "ISK", "JPY", "KRW", "MXN", "MYR", "NOK", "NZD",
-            "PHP", "PLN", "RON", "RUB", "SEK", "SGD", "THB", "TRY", "USD",
-            "ZAR"}
-        :param to_currency: The target currency to convert to.
-            May be any of: currency_set = {"AUD", "BGN", "BRL", "CAD", "CHF",
-            "CNY", "CZK", "DKK", "EUR", "GBP", "HKD", "HRK", "HUF", "IDR",
-            "ILS", "INR", "ISK", "JPY", "KRW", "MXN", "MYR", "NOK", "NZD",
-            "PHP", "PLN", "RON", "RUB", "SEK", "SGD", "THB", "TRY", "USD",
-            "ZAR"}
-        :param historical_date: If supplied, get exchange rate on a certain\
-        date. If not supplied, get the latest exchange rate. The exchange\
-        rates go back to Jan. 4, 1999.
-
-        :Setup:
-        .. code-block:: python
-
-            import pandas as pd
-            import janitor
-            from datetime import date
-
-            data_dict = {
-                "a": [1.23452345, 2.456234, 3.2346125] * 3,
-                "Bell__Chart": [1/3, 2/7, 3/2] * 3,
-                "decorated-elephant": [1/234, 2/13, 3/167] * 3,
-                "animals": ["rabbit", "leopard", "lion"] * 3,
-                "cities": ["Cambridge", "Shanghai", "Basel"] * 3,
-            }
-
-            example_dataframe = pd.DataFrame(data_dict)
-
-        :Example: Converting a column from one currency to another using rates
-        from 01/01/2018:
-
-        .. code-block:: python
-
-            example_dataframe.convert_currency('a', from_currency='USD',
-            to_currency='EUR', historical_date=date(2018,1,1))
-
-        :Output:
-        .. code-block:: python
-
-                      a  Bell__Chart  decorated-elephant  animals     cities
-            0  1.029370     0.333333            0.004274   rabbit  Cambridge
-            1  2.048056     0.285714            0.153846  leopard   Shanghai
-            2  2.697084     1.500000            0.017964     lion      Basel
-            3  1.029370     0.333333            0.004274   rabbit  Cambridge
-            4  2.048056     0.285714            0.153846  leopard   Shanghai
-            5  2.697084     1.500000            0.017964     lion      Basel
-            6  1.029370     0.333333            0.004274   rabbit  Cambridge
-            7  2.048056     0.285714            0.153846  leopard   Shanghai
-            8  2.697084     1.500000            0.017964     lion      Basel
-
-        """
+    Converts a column from one currency to another, with an option to
+    convert based on historical exchange values.
+
+    :param df: A pandas dataframe.
+    :param colname: Name of the new column. Should be a string, in order
+        for the column name to be compatible with the Feather binary
+        format (this is a useful thing to have).
+    :param from_currency: The base currency to convert from.
+        May be any of: currency_set = {"AUD", "BGN", "BRL", "CAD", "CHF",
+        "CNY", "CZK", "DKK", "EUR", "GBP", "HKD", "HRK", "HUF", "IDR",
+        "ILS", "INR", "ISK", "JPY", "KRW", "MXN", "MYR", "NOK", "NZD",
+        "PHP", "PLN", "RON", "RUB", "SEK", "SGD", "THB", "TRY", "USD",
+        "ZAR"}
+    :param to_currency: The target currency to convert to.
+        May be any of: currency_set = {"AUD", "BGN", "BRL", "CAD", "CHF",
+        "CNY", "CZK", "DKK", "EUR", "GBP", "HKD", "HRK", "HUF", "IDR",
+        "ILS", "INR", "ISK", "JPY", "KRW", "MXN", "MYR", "NOK", "NZD",
+        "PHP", "PLN", "RON", "RUB", "SEK", "SGD", "THB", "TRY", "USD",
+        "ZAR"}
+    :param historical_date: If supplied, get exchange rate on a certain\
+    date. If not supplied, get the latest exchange rate. The exchange\
+    rates go back to Jan. 4, 1999.
+
+    :Setup:
+
+    .. code-block:: python
+
+        import pandas as pd
+        import janitor
+        from datetime import date
+
+        data_dict = {
+            "a": [1.23452345, 2.456234, 3.2346125] * 3,
+            "Bell__Chart": [1/3, 2/7, 3/2] * 3,
+            "decorated-elephant": [1/234, 2/13, 3/167] * 3,
+            "animals": ["rabbit", "leopard", "lion"] * 3,
+            "cities": ["Cambridge", "Shanghai", "Basel"] * 3,
+        }
+
+        example_dataframe = pd.DataFrame(data_dict)
+
+    :Example: Converting a column from one currency to another using rates
+
+    from 01/01/2018:
+
+    .. code-block:: python
+
+        example_dataframe.convert_currency('a', from_currency='USD',
+        to_currency='EUR', historical_date=date(2018,1,1))
+
+    :Output:
+
+    .. code-block:: python
+
+                    a  Bell__Chart  decorated-elephant  animals     cities
+        0  1.029370     0.333333            0.004274   rabbit  Cambridge
+        1  2.048056     0.285714            0.153846  leopard   Shanghai
+        2  2.697084     1.500000            0.017964     lion      Basel
+        3  1.029370     0.333333            0.004274   rabbit  Cambridge
+        4  2.048056     0.285714            0.153846  leopard   Shanghai
+        5  2.697084     1.500000            0.017964     lion      Basel
+        6  1.029370     0.333333            0.004274   rabbit  Cambridge
+        7  2.048056     0.285714            0.153846  leopard   Shanghai
+        8  2.697084     1.500000            0.017964     lion      Basel
+
+    """
 
     rate = _convert_currency(from_currency, to_currency, historical_date)
 
diff --git a/janitor/functions.py b/janitor/functions.py
--- a/janitor/functions.py
+++ b/janitor/functions.py
@@ -22,8 +22,11 @@ def _strip_underscores(df, strip_underscores=None):
     """
     Strip underscores from DataFrames column names.
     Underscores can be stripped from the beginning, end or both.
+
     .. code-block:: python
+
         df = _strip_underscores(df, strip_underscores='left')
+
     :param df: The pandas DataFrame object.
     :param strip_underscores: (optional) Removes the outer underscores from all
         column names. Default None keeps outer underscores. Values can be
@@ -56,20 +59,31 @@ def clean_names(
 ):
     """
     Clean column names.
+
     Takes all column names, converts them to lowercase, then replaces all
     spaces with underscores.
+
     Functional usage example:
+
     .. code-block:: python
+
         df = clean_names(df)
+
     Method chaining example:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         df = pd.DataFrame(...).clean_names()
+
     :Example of transformation:
+
     .. code-block:: python
+
         Columns before: First Name, Last Name, Employee Status, Subject
         Columns after: first_name, last_name, employee_status, subject
+
     :param df: The pandas DataFrame object.
     :param strip_underscores: (optional) Removes the outer underscores from all
         column names. Default None keeps outer underscores. Values can be
@@ -132,17 +146,27 @@ def _remove_special(col):
 def remove_empty(df):
     """
     Drop all rows and columns that are completely null.
+
     Implementation is shamelessly copied from `StackOverflow`_.
+
     .. _StackOverflow: https://stackoverflow.com/questions/38884538/python-pandas-find-all-rows-where-all-values-are-nan  # noqa: E501
+
     Functional usage example:
+
     .. code-block:: python
+
         df = remove_empty(df)
+
     Method chaining example:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         df = pd.DataFrame(...).remove_empty()
+
     :param df: The pandas DataFrame object.
+
     :returns: A pandas DataFrame.
     """
     nanrows = df.index[df.isnull().all(axis=1)]
@@ -158,14 +182,22 @@ def remove_empty(df):
 def get_dupes(df, columns=None):
     """
     Return all duplicate rows.
+
     Functional usage example:
+
     .. code-block:: python
-        get_dupes(df)
+
+        df = pd.DataFrame(...)
+        df = get_dupes(df)
+
     Method chaining example:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         df = pd.DataFrame(...).get_dupes()
+
     :param df: The pandas DataFrame object.
     :param str/iterable columns: (optional) A column name or an iterable (list
         or tuple) of column names. Following pandas API, this only considers
@@ -181,16 +213,23 @@ def get_dupes(df, columns=None):
 def encode_categorical(df, columns):
     """
     Encode the specified columns as categorical column in pandas.
+
     Functional usage example:
+
     .. code-block:: python
+
         encode_categorical(df, columns="my_categorical_column")  # one way
+
     Method chaining example:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         df = pd.DataFrame(...)
         categorical_cols = ['col1', 'col2', 'col4']
         df = df.encode_categorical(columns=categorical_cols)
+
     :param df: The pandas DataFrame object.
     :param str/iterable columns: A column name or an iterable (list or tuple)
         of column names.
@@ -216,20 +255,29 @@ def encode_categorical(df, columns):
 def label_encode(df, columns):
     """
     Convert labels into numerical data.
+
     This function will create a new column with the string "_enc" appended
     after the original column's name. Consider this to be syntactic sugar.
+
     This function behaves differently from `encode_categorical`. This function
     creates a new column of numeric data. `encode_categorical` replaces the
     dtype of the original column with a "categorical" dtype.
+
     Functional usage example:
+
     .. code-block:: python
+
         label_encode(df, columns="my_categorical_column")  # one way
+
     Method chaining example:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         categorical_cols = ['col1', 'col2', 'col4']
         df = pd.DataFrame(...).label_encode(columns=categorical_cols)
+
     :param df: The pandas DataFrame object.
     :param str/iterable columns: A column name or an iterable (list or tuple)
         of column names.
@@ -256,22 +304,30 @@ def label_encode(df, columns):
 def get_features_targets(df, target_columns, feature_columns=None):
     """
     Get the features and targets as separate DataFrames/Series.
+
     The behaviour is as such:
     - `target_columns` is mandatory.
     - If `feature_columns` is present, then we will respect the column names
-      inside there.
+    inside there.
     - If `feature_columns` is not passed in, then we will assume that the
-      rest of the columns are feature columns, and return them.
+    rest of the columns are feature columns, and return them.
+
     Functional usage example:
+
     .. code-block:: python
+
         X, y = get_features_targets(df, target_columns="measurement")
+
     Method chaining example:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         df = pd.DataFrame(...)
         target_cols = ['output1', 'output2']
         X, y = df.get_features_targets(target_columns=target_cols)  # noqa: E501
+
     :param df: The pandas DataFrame object.
     :param str/iterable target_columns: Either a column name or an iterable
         (list or tuple) of column names that are the target(s) to be predicted.
@@ -300,17 +356,25 @@ def get_features_targets(df, target_columns, feature_columns=None):
 def rename_column(df, old, new):
     """
     Rename a column in place.
+
     Functional usage example:
+
     .. code-block:: python
+
         df = rename_column("old_column_name", "new_column_name")
+
     Method chaining example:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         df = pd.DataFrame(...).rename_column("old_column_name", "new_column_name")  # noqa: E501
+
     This is just syntactic sugar/a convenience function for renaming one column
     at a time. If you are convinced that there are multiple columns in need of
     changing, then use the :py:meth:`pandas.DataFrame.rename` method.
+
     :param str old: The old column name.
     :param str new: The new column name.
     :returns: A pandas DataFrame.
@@ -324,20 +388,32 @@ def reorder_columns(
 ) -> pd.DataFrame:
     """
     Reorder DataFrame columns by specifying desired order as list of col names
-    Columns not specified retain their order and follow after specified cols
+
+    Columns not specified retain their order and follow after specified cols.
+
     Validates column_order to ensure columns are all present in DataFrame.
+
     Functional usage example:
+
     Given `DataFrame` with column names `col1`, `col2`, `col3`:
+
     .. code-block:: python
+
         df = reorder_columns(df, ['col2', 'col3'])
+
     Method chaining example:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         df = pd.DataFrame(...).reorder_columns(['col2', 'col3'])
+
     The column order of `df` is now `col2`, `col3`, `col1`.
+
     Internally, this function uses `DataFrame.reindex` with `copy=False`
     to avoid unnecessary data duplication.
+
     :param df: `DataFrame` to reorder
     :param column_order: A list of column names or Pandas `Index`
         specifying their order in the returned `DataFrame`.
@@ -366,21 +442,31 @@ def reorder_columns(
 @pf.register_dataframe_method
 def coalesce(df, columns, new_column_name):
     """
+
     Coalesces two or more columns of data in order of column names provided.
+
     Functional usage example:
+
     .. code-block:: python
+
         df = coalesce(df, columns=['col1', 'col2'])
+
     Method chaining example:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         df = pd.DataFrame(...).coalesce(['col1', 'col2'])
+
     The result of this function is that we take the first non-null value across
     rows.
+
     This is more syntactic diabetes! For R users, this should look familiar to
     `dplyr`'s `coalesce` function; for Python users, the interface
     should be more intuitive than the :py:meth:`pandas.Series.combine_first`
     method (which we're just using internally anyways).
+
     :param df: A pandas DataFrame.
     :param columns: A list of column names.
     :param str new_column_name: The new column name after combining.
@@ -400,16 +486,25 @@ def _coalesce(series1, series2):
 def convert_excel_date(df, column):
     """
     Convert Excel's serial date format into Python datetime format.
+
     Implementation is also from `Stack Overflow`.
+
     .. _Stack Overflow: https://stackoverflow.com/questions/38454403/convert-excel-style-date-with-pandas  # noqa: E501
+
     Functional usage example:
+
     .. code-block:: python
+
         df = convert_excel_date(df, column='date')
+
     Method chaining example:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         df = pd.DataFrame(...).convert_excel_date('date')
+
     :param df: A pandas DataFrame.
     :param str column: A column name.
     :returns: A pandas DataFrame with corrected dates.
@@ -424,15 +519,23 @@ def convert_excel_date(df, column):
 def fill_empty(df, columns, value):
     """
     Fill `NaN` values in specified columns with a given value.
+
     Super sugary syntax that wraps :py:meth:`pandas.DataFrame.fillna`.
+
     Functional usage example:
+
     .. code-block:: python
+
         df = fill_empty(df, columns=['col1', 'col2'], value=0)
+
     Method chaining example:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         df = pd.DataFrame(...).fill_empty(df, columns='col1', value=0)
+
     :param df: A pandas DataFrame.
     :param columns: Either a `str` or `list` or `tuple`. If a string is passed
         in, then only that column will be filled; if a list or tuple of strings
@@ -443,12 +546,16 @@ def fill_empty(df, columns, value):
         for col in columns:
             assert (
                 col in df.columns
-            ), "{col} missing from dataframe columns!".format(col=col)
+            ), "{col} missing from dataframe columns!".format(
+                col=col
+            )
             df[col] = df[col].fillna(value)
     else:
         assert (
             columns in df.columns
-        ), "{col} missing from dataframe columns!".format(col=columns)
+        ), "{col} missing from dataframe columns!".format(
+            col=columns
+        )
         df[columns] = df[columns].fillna(value)
 
     return df
@@ -458,16 +565,24 @@ def fill_empty(df, columns, value):
 def expand_column(df, column, sep, concat=True):
     """
     Expand a categorical column with multiple labels into dummy-coded columns.
+
     Super sugary syntax that wraps :py:meth:`pandas.Series.str.get_dummies`.
+
     Functional usage example:
+
     .. code-block:: python
+
         df = expand_column(df, column='col_name',
                            sep=', ')  # note space in sep
+
     Method chaining example:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         df = pd.DataFrame(...).expand_column(df, column='col_name', sep=', ')
+
     :param df: A pandas DataFrame.
     :param column: A `str` indicating which column to expand.
     :param sep: The delimiter. Example delimiters include `|`, `, `, `,` etc.
@@ -489,19 +604,27 @@ def concatenate_columns(
 ):
     """
     Concatenates the set of columns into a single column.
+
     Used to quickly generate an index based on a group of columns.
+
     Functional usage example:
+
     .. code-block:: python
+
         df = concatenate_columns(df,
                                  columns=['col1', 'col2'],
                                  new_column_name='id',
                                  sep='-')
+
     Method chaining example:
+
     .. code-block:: python
+
         df = (pd.DataFrame(...).
               concatenate_columns(columns=['col1', 'col2'],
                                   new_column_name='id',
                                   sep='-'))
+
     :param df: A pandas DataFrame.
     :param columns: A list of columns to concatenate together.
     :param new_column_name: The name of the new column.
@@ -523,20 +646,29 @@ def concatenate_columns(
 def deconcatenate_column(df, column: str, new_column_names: List, sep: str):
     """
     De-concatenates a single column into multiple columns.
+
     This is the inverse of the `concatenate_columns` function.
+
     Used to quickly split columns out of a single column.
+
     Functional usage example:
+
     .. code-block:: python
+
         df = deconcatenate_columns(df,
                                    column='id',
                                    new_column_names=['col1', 'col2'],
                                    sep='-')
+
     Method chaining example:
+
     .. code-block:: python
+
         df = (pd.DataFrame(...).
               deconcatenate_columns(columns='id',
                                     new_column_name=['col1', 'col2'],
                                     sep='-'))
+
     :param df: A pandas DataFrame.
     :param column: The column to split.
     :param new_column_names: A list of new column names post-splitting.
@@ -559,35 +691,51 @@ def filter_string(
 ):
     """
     Filter a string-based column according to whether it contains a substring.
+
     This is super sugary syntax that builds on top of `filter_on` and
     `pandas.Series.str.contains`.
+
     Because this uses internally `pandas.Series.str.contains`, which allows a
     regex string to be passed into it, thus `search_string` can also be a regex
     pattern.
+
     This function allows us to method chain filtering operations:
+
     .. code-block:: python
+
         df = (pd.DataFrame(...)
               .filter_string('column', search_string='pattern', complement=False)  # noqa: E501
               ...)  # chain on more data preprocessing.
+
     This stands in contrast to the in-place syntax that is usually used:
+
     .. code-block:: python
+
         df = pd.DataFrame(...)
         df = df[df['column'].str.contains('pattern')]]
+
     As can be seen here, the API design allows for a more seamless flow in
     expressing the filtering operations.
+
     Functional usage example:
+
     .. code-block:: python
+
         df = filter_string(df,
                            column='column',
                            search_string='pattern'
                            complement=False)
+
     Method chaining example:
+
     .. code-block:: python
+
         df = (pd.DataFrame(...)
               .filter_string(column='column',
                              search_string='pattern'
                              complement=False)
               ...)
+
     :param df: A pandas DataFrame.
     :param column: The column to filter. The column should contain strings.
     :param search_string: A regex pattern or a (sub-)string to search.
@@ -601,29 +749,44 @@ def filter_string(
 def filter_on(df, criteria, complement=False):
     """
     Return a dataframe filtered on a particular criteria.
+
     This function allows us to method chain filtering operations:
+
     .. code-block:: python
+
         df = (pd.DataFrame(...)
               .filter_on(df['value'] < 3, complement=False)
               ...)  # chain on more data preprocessing.
+
     This stands in contrast to the in-place syntax that is usually used:
+
     .. code-block:: python
+
         df = pd.DataFrame(...)
         df = df[df['value'] < 3]
+
     As with the `filter_string` function, a more seamless flow can be expressed
     in the code.
+
     Functional usage example:
+
     .. code-block:: python
+
         df = filter_on(df,
-                           df['value'] < 3,
-                           complement=False)
+                       df['value'] < 3,
+                       complement=False)
+
     Method chaining example:
+
     .. code-block:: python
+
         df = (pd.DataFrame(...)
               .filter_on(df['value'] < 3
                              complement=False)
               ...)
+
     Credit to Brant Peterson for the name.
+
     :param df: A pandas DataFrame.
     :param criteria: A filtering criteria that returns an array or Series of
         booleans, on which pandas can filter on.
@@ -639,10 +802,15 @@ def filter_on(df, criteria, complement=False):
 def remove_columns(df: pd.DataFrame, columns: List):
     """
     Removes the set of columns specified in cols.
+
     Intended to be the method-chaining alternative to `del df[col]`.
+
     Method chaining example:
+
     .. code-block:: python
+
         df = pd.DataFrame(...).remove_columns(cols=['col1', ['col2']])
+
     :param df: A pandas DataFrame
     :param columns: The columns to remove.
     """
@@ -655,11 +823,17 @@ def remove_columns(df: pd.DataFrame, columns: List):
 def change_type(df, column: str, dtype):
     """
     Changes the type of a column.
+
     Intended to be the method-chaining alternative to::
+
         df[col] = df[col].astype(dtype)
+
     Method chaining example:
+
     .. code-block:: python
+
         df = pd.DataFrame(...).change_type('col1', str)
+
     :param df: A pandas dataframe.
     :param column: A column in the dataframe.
     :param dtype: The datatype to convert to. Should be one of the standard
@@ -673,17 +847,26 @@ def change_type(df, column: str, dtype):
 def add_column(df, col_name: str, value, fill_remaining: bool = False):
     """
     Adds a column to the dataframe.
+
     Intended to be the method-chaining alternative to::
+
         df[col_name] = value
+
     Method chaining example adding a column with only a single value:
+
     .. code-block:: python
+
         # This will add a column with only one value.
         df = pd.DataFrame(...).add_column(col_name="new_column", 2)
+
     Method chaining example adding a column with more than one value:
+
     .. code-block:: python
+
         # This will add a column with an iterable of values.
         vals = [1, 2, 5, ..., 3, 4]  # of same length as the dataframe.
         df = pd.DataFrame(...).add_column(col_name="new_column", vals)
+
     :param df: A pandas dataframe.
     :param col_name: Name of the new column. Should be a string, in order
         for the column name to be compatible with the Feather binary
@@ -692,8 +875,11 @@ def add_column(df, col_name: str, value, fill_remaining: bool = False):
     :param fill_remaining: If value is a tuple or list that is smaller than
         the number of rows in the DataFrame, repeat the list or tuple
         (R-style) to the end of the DataFrame.
+
     :Setup:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         data = {
@@ -704,11 +890,17 @@ def add_column(df, col_name: str, value, fill_remaining: bool = False):
             "cities": ["Cambridge", "Shanghai", "Basel"] * 3,
         }
         df = pd.DataFrame(data)
+
     :Example 1: Create a new column with a single value:
+
     .. code-block:: python
+
         df.add_column("city_pop", 100000)
+
     :Output:
+
     .. code-block:: python
+
            a  Bell__Chart  decorated-elephant  animals     cities  city_pop
         0  1            1                   1   rabbit  Cambridge    100000
         1  2            2                   2  leopard   Shanghai    100000
@@ -719,12 +911,18 @@ def add_column(df, col_name: str, value, fill_remaining: bool = False):
         6  1            1                   1   rabbit  Cambridge    100000
         7  2            2                   2  leopard   Shanghai    100000
         8  3            3                   3     lion      Basel    100000
+
     :Example 2: Create a new column with an iterator \
     which fills to the column size:
+
     .. code-block:: python
+
         df.add_column("city_pop", range(3), fill_remaining=True)
+
     :Output:
+
     .. code-block:: python
+
            a  Bell__Chart  decorated-elephant  animals     cities  city_pop
         0  1            1                   1   rabbit  Cambridge         0
         1  2            2                   2  leopard   Shanghai         1
@@ -735,11 +933,17 @@ def add_column(df, col_name: str, value, fill_remaining: bool = False):
         6  1            1                   1   rabbit  Cambridge         0
         7  2            2                   2  leopard   Shanghai         1
         8  3            3                   3     lion      Basel         2
+
     :Example 3: Add new column based on mutation of other columns:
+
     .. code-block:: python
+
         df.add_column("city_pop", df.Bell__Chart - 2 * df.a)
+
     :Output:
+
     .. code-block:: python
+
            a  Bell__Chart  decorated-elephant  animals     cities  city_pop
         0  1            1                   1   rabbit  Cambridge        -1
         1  2            2                   2  leopard   Shanghai        -2
@@ -801,14 +1005,20 @@ def add_columns(df: pd.DataFrame, fill_remaining: bool = False, **kwargs):
     """
     Method to augment `add_column` with ability to add multiple columns in
     one go. This replaces the need for multiple `add_column` calls.
+
     Usage is through supplying kwargs where the key is the col name and the
     values correspond to the values of the new DataFrame column.
+
     Values passed can be scalar or iterable (list, ndarray, etc.)
+
     Usage example:
+
     .. code-block:: python
+
         x = 3
         y = np.arange(0, 10)
         df = pd.DataFrame(...).add_columns(x=x, y=y)
+
     :param df: A pandas dataframe.
     :param fill_remaining: If value is a tuple or list that is smaller than
         the number of rows in the DataFrame, repeat the list or tuple
@@ -829,9 +1039,11 @@ def add_columns(df: pd.DataFrame, fill_remaining: bool = False, **kwargs):
 def limit_column_characters(df, column_length: int, col_separator: str = "_"):
     """
     Truncates column sizes to a specific length.
+
     Method chaining will truncate all columns to a given length and append
     a given separator character with the index of duplicate columns, except
     for the first distinct column name.
+
     :param df: A pandas dataframe.
     :param column_length: Character length for which to truncate all columns.
         The column separator value and number for duplicate column name does
@@ -843,8 +1055,11 @@ def limit_column_characters(df, column_length: int, col_separator: str = "_"):
         values. I think an underscore looks nicest, however a period is a
         common option as well. Supply an empty string (i.e. '') to remove the
         separator.
+
     :Example Setup:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         data_dict = {
@@ -854,12 +1069,18 @@ def limit_column_characters(df, column_length: int, col_separator: str = "_"):
             "another_really_longer_name_for_a_column": list("lllongname"),
             "this_is_getting_out_of_hand": list("longername"),
         }
-    :Example 1: Standard truncation:
+
+    :Example: Standard truncation:
+
     .. code-block:: python
+
         example_dataframe = pd.DataFrame(data_dict)
         example_dataframe.limit_column_characters(7)
+
     :Output:
+
     .. code-block:: python
+
                really_  another another_1 this_is
         0        0        0         l       l
         1        1        2         l       o
@@ -871,11 +1092,16 @@ def limit_column_characters(df, column_length: int, col_separator: str = "_"):
         7        7       14         a       a
         8        8       16         m       m
         9        9       18         e       e
-    :Example 2: Standard truncation with different separator character:
+
+    :Example: Standard truncation with different separator character:
+
     .. code-block:: python
+
         example_dataframe2 = pd.DataFrame(data_dict)
         example_dataframe2.limit_column_characters(7, ".")
+
     .. code-block:: python
+
                really_  another another.1 this_is
         0        0        0         l       l
         1        1        2         l       o
@@ -932,17 +1158,22 @@ def row_to_names(
     remove_rows_above: bool = False,
 ):
     """
-    Elevates a row to be the column names of a DataFrame. Contains options to
-    remove the elevated row from the DataFrame along with removing the rows
-    above the selected row.
+    Elevates a row to be the column names of a DataFrame.
+
+    Contains options to remove the elevated row from the DataFrame along with
+    removing the rows above the selected row.
+
     :param df: A pandas DataFrame.
     :param row_number: The row containing the variable names
     :param remove_row: Whether the row should be removed from the DataFrame.
         Defaults to False.
     :param remove_rows_above: Whether the rows above the selected row should
         be removed from the DataFrame. Defaults to False.
+
     :Setup:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         data_dict = {
@@ -952,12 +1183,18 @@ def row_to_names(
             "animals": ["rabbit", "leopard", "lion"] * 3,
             "cities": ["Cambridge", "Shanghai", "Basel"] * 3
         }
-    :Example 1: Move first row to column names:
+
+    :Example: Move first row to column names:
+
     .. code-block:: python
+
         example_dataframe = pd.DataFrame(data_dict)
         example_dataframe.row_to_names(0)
+
     :Output:
+
     .. code-block:: python
+
            1  1  1   rabbit  Cambridge
         0  1  1  1   rabbit  Cambridge
         1  2  2  2  leopard   Shanghai
@@ -967,12 +1204,18 @@ def row_to_names(
         5  3  3  3     lion      Basel
         6  1  1  1   rabbit  Cambridge
         7  2  2  2  leopard   Shanghai
-    :Example 2: Move first row to column names and remove row:
+
+    :Example: Move first row to column names and remove row:
+
     .. code-block:: python
+
         example_dataframe = pd.DataFrame(data_dict)
         example_dataframe.row_to_names(0, remove_row=True)
+
     :Output:
+
     .. code-block:: python
+
            1  1  1   rabbit  Cambridge
         1  2  2  2  leopard   Shanghai
         2  3  3  3     lion      Basel
@@ -982,14 +1225,20 @@ def row_to_names(
         6  1  1  1   rabbit  Cambridge
         7  2  2  2  leopard   Shanghai
         8  3  3  3     lion      Basel
-    :Example 3: Move first row to column names, remove row, \
+
+    :Example: Move first row to column names, remove row, \
     and remove rows above selected row:
+
     .. code-block:: python
+
         example_dataframe = pd.DataFrame(data_dict)
         example_dataframe.row_to_names(2, remove_row=True, \
             remove_rows_above=True)
+
     :Output:
+
     .. code-block:: python
+
            3  3  3     lion      Basel
         3  1  1  1   rabbit  Cambridge
         4  2  2  2  leopard   Shanghai
@@ -1019,14 +1268,20 @@ def round_to_fraction(
 ):
     """
     Round all values in a column to a fraction.
+
     Also, optionally round to a specified number of digits.
+
     :param number: The number to round
     :param denominator: The denominator of the fraction for rounding
     :param digits: The number of digits for rounding after rounding to the
         fraction. Default is np.inf (i.e. no subsequent rounding)
+
     Taken from https://github.com/sfirke/janitor/issues/235
+
     :Example Setup:
+
     .. code-block:: python
+
         import pandas as pd
         import janitor
         data_dict = {
@@ -1036,12 +1291,18 @@ def round_to_fraction(
             "animals": ["rabbit", "leopard", "lion"] * 3,
             "cities": ["Cambridge", "Shanghai", "Basel"] * 3,
         }
-    :Example 1: Rounding the first column to the nearest half:
+
+    :Example: Rounding the first column to the nearest half:
+
     .. code-block:: python
+
         example_dataframe = pd.DataFrame(data_dict)
         example_dataframe.round_to_fraction('a', 2)
+
     :Output:
+
     .. code-block:: python
+
              a  Bell__Chart  decorated-elephant  animals     cities
         0  1.0     0.333333            0.004274   rabbit  Cambridge
         1  2.5     0.285714            0.153846  leopard   Shanghai
@@ -1052,12 +1313,18 @@ def round_to_fraction(
         6  1.0     0.333333            0.004274   rabbit  Cambridge
         7  2.5     0.285714            0.153846  leopard   Shanghai
         8  3.0     1.500000            0.017964     lion      Basel
-    :Example 2: Rounding the first column to nearest third:
+
+    :Example: Rounding the first column to nearest third:
+
     .. code-block:: python
+
         example_dataframe2 = pd.DataFrame(data_dict)
         example_dataframe2.limit_column_characters('a', 3)
+
     :Output:
+
     .. code-block:: python
+
                   a  Bell__Chart  decorated-elephant  animals     cities
         0  1.333333     0.333333            0.004274   rabbit  Cambridge
         1  2.333333     0.285714            0.153846  leopard   Shanghai
@@ -1068,13 +1335,19 @@ def round_to_fraction(
         6  1.333333     0.333333            0.004274   rabbit  Cambridge
         7  2.333333     0.285714            0.153846  leopard   Shanghai
         8  3.333333     1.500000            0.017964     lion      Basel
+
     :Example 3: Rounding the first column to the nearest third and rounding \
     each value to the 10,000th place:
+
     .. code-block:: python
+
         example_dataframe2 = pd.DataFrame(data_dict)
         example_dataframe2.limit_column_characters('a', 3, 4)
+
     :Output:
+
     .. code-block:: python
+
                 a  Bell__Chart  decorated-elephant  animals     cities
         0  1.3333     0.333333            0.004274   rabbit  Cambridge
         1  2.3333     0.285714            0.153846  leopard   Shanghai
@@ -1114,21 +1387,32 @@ def _round_to_fraction(number, denominator, digits=np.inf):
 def transform_column(df, col_name: str, function, dest_col_name: str = None):
     """
     Transforms the given column in-place using the provided function.
+
     Let's say we wanted to apply a log10 transform a column of data.
+
     Originally one would write code like this:
+
     .. code-block:: python
+
         # YOU NO LONGER NEED TO WRITE THIS!
         df[col_name] = df[col_name].apply(function)
+
     With the method chaining syntax, we can do the following instead:
+
     .. code-block:: python
+
         df = (
             pd.DataFrame(...)
             .transform(col_name, function)
         )
+
     With the functional syntax:
+
     .. code-block:: python
+
         df = pd.DataFrame(...)
         df = transform(df, col_name, function)
+
     :param df: A pandas DataFrame.
     :param col_name: The column to transform.
     :param function: A function to apply on the column.
@@ -1149,19 +1433,28 @@ def min_max_scale(
 ):
     """
     Scales data to between a minimum and maximum value.
+
     If `minimum` and `maximum` are provided, the true min/max of the
     `DataFrame` or column is ignored in the scaling process and replaced with
     these values, instead.
+
     One can optionally set a new target minimum and maximum value using the
     `new_min` and `new_max` keyword arguments. This will result in the
     transformed data being bounded between `new_min` and `new_max`.
+
     If a particular column name is specified, then only that column of data
     are scaled. Otherwise, the entire dataframe is scaled.
+
     Method chaining example:
+
     .. code-block:: python
+
         df = pd.DataFrame(...).min_max_scale(col_name="a")
+
     Setting custom minimum and maximum:
+
     .. code-block:: python
+
         df = (
             pd.DataFrame(...)
             .min_max_scale(
@@ -1170,9 +1463,12 @@ def min_max_scale(
                 new_max=10
             )
         )
+
     Setting a min and max that is not based on the data, while applying to
     entire dataframe:
+
     .. code-block:: python
+
         df = (
             pd.DataFrame(...)
             .min_max_scale(
@@ -1182,11 +1478,13 @@ def min_max_scale(
                 new_max=1,
             )
         )
+
     The aforementioned example might be applied to something like scaling the
     isoelectric points of amino acids. While technically they range from
     approx 3-10, we can also think of them on the pH scale which ranges from
     1 to 14. Hence, 3 gets scaled not to 0 but approx. 0.15 instead, while 10
     gets scaled to approx. 0.69 instead.
+
     :param df: A pandas DataFrame.
     :param old_min, old_max (optional): Overrides for the current minimum and
         maximum values of the data to be transformed.
@@ -1231,27 +1529,34 @@ def collapse_levels(df: pd.DataFrame, sep: str = "_"):
     """
     Given a `DataFrame` containing multi-level columns, flatten to single-
     level by string-joining the column labels in each level.
+
     After a `groupby` / `aggregate` operation where `.agg()` is passed a
     list of multiple aggregation functions, a multi-level `DataFrame` is
     returned with the name of the function applied in the second level.
+
     It is sometimes convenient for later indexing to flatten out this
     multi-level configuration back into a single level. This function does
     this through a simple string-joining of all the names across different
     levels in a single column.
+
     Method chaining example given two value columns `['var1', 'var2']`:
+
     .. code-block:: python
+
         df = (
             pd.DataFrame(...)
             .groupby('mygroup')
             .agg(['mean', 'median'])
             .collapse_levels(sep='_')
         )
+
     Before applying `.collapse_levels`, the `.agg` operation returns a
     multi-level column `DataFrame` whose columns are (level 1, level 2):
     `[('mygroup', ''), ('var1', 'mean'), ('var1', 'median'), ('var2', 'mean'),
     ('var2', 'median')]`
     `.collapse_levels` then flattens the column names to:
     `['mygroup', 'var1_mean', 'var1_median', 'var2_mean', 'var2_median']`
+
     :param df: A pandas DataFrame.
     :param sep: String separator used to join the column level names
     :returns: df
@@ -1273,8 +1578,11 @@ def collapse_levels(df: pd.DataFrame, sep: str = "_"):
 def check(varname: str, value, expected_types: list):
     """
     One-liner syntactic sugar for checking types.
-    Should be used like this:
+
+    Should be used like this::
+
         check('x', x, [int, float])
+
     :param varname: The name of the variable.
     :param value: The value of the varname.
     :param expected_types: The types we expect the item to be.


Test patch:
diff --git a/tests/test_functions.py b/tests/test_functions.py
--- a/tests/test_functions.py
+++ b/tests/test_functions.py
@@ -295,9 +295,7 @@ def test_single_column_fail_label_encode():
     with pytest.raises(AssertionError):
         df = pd.DataFrame(
             {"a": ["hello", "hello", "sup"], "b": [1, 2, 3]}
-        ).label_encode(
-            columns="c"
-        )  # noqa: 841
+        ).label_encode(columns="c")  # noqa: 841
 
 
 def test_multicolumn_label_encode():