def linear(input_df, input_col, output_col,
           start=None, end=None,
           output_min=1, output_max=9):
    """
    Rescale a column in a DataFrame linearly.

    If argument start is greater than end, the rescaling is in the
    same direction as values in the input column, i.e., smaller (bigger) values
    in the input column correspond to smaller (bigger) values in the output.
    If argument start is less than end, the rescaling is in the reverse
    direction as values in the input column.
    The start and end of the input column do not necessarily to be the minimum
    and maximum of the input column. Values beyond the specified bound will be
    assigned to output_min and output_max, depending on which side they are on.

    Parameters
    ----------
    input_df : DataFrame or GeoDataFrame
        Input DataFrame containing a column need to be rescaled.
    input_col : str
        Name of the old column.
    output_col : str
        Name of the new column.
    start : int or float
        Value from which the rescaling starts.
    end : int or float
        Value from which the rescaling ends.
    output_min : int or float
        The minimum value of the output column.
    output_max : int or float
        The maximum value of the output column.

    Returns
    -------
    input_df : DataFrame or GeoDataFrame
        Output DataFrame containing the rescaled column.

    """
    if start is None:
        start = input_df[input_col].min()
    if end is None:
        end = input_df[input_col].max()
    input_range = abs(end - start)
    output_range = abs(output_max - output_min)
    if end > start:
        input_df[output_col] = (
            output_min
            + (input_df[input_col] - start) * output_range / input_range
        )
        input_df.loc[input_df[input_col] > end, output_col] = output_max
        input_df.loc[input_df[input_col] < start, output_col] = output_min
    else:
        input_df[output_col] = (
            output_max
            - (input_df[input_col] - end) * output_range / input_range
        )
        input_df.loc[input_df[input_col] < end, output_col] = output_max
        input_df.loc[input_df[input_col] > start, output_col] = output_min
    return input_df