Return a transformed DataFrame.

    Transform data_frame along the given axis. By default, each row will be normalized (axis=0).

    Parameters
    -----------
    data_frame : DataFrame
        Data to be normalized.
    axis : int, optional
        0 (default) to normalize each row, 1 to normalize each column.
    method : str, optional
        Valid methods are:
        
        -  "vector" : Default for normalization by row (axis=0).
           Normalize along axis as a vector with norm `norm`
        -  "last" : Linear normalization setting last value along the axis to `norm`
        -  "first" : Default for normalization of columns (axis=1).
           Linear normalization setting first value along the given axis to `norm`
        -  "mean" : Normalize so that the mean of each vector along the given axis is `norm`
    norm : float, optional
        Target value of normalization, defaults to 1.0.
    labels : DataFrame, optional
        Labels may be passed as keyword argument, in which
        case the label values will also be normalized and returned.

    Returns
    -----------
    df : DataFrame
        Normalized data.
    labels : DataFrame, optional
        Normalized labels, if provided as input.

    Notes
    -----------
    If labels are real-valued, they should also be normalized.

    ..
        Having row_norms as a numpy array should be benchmarked against 
        using a DataFrame:
        http://stackoverflow.com/questions/12525722/normalize-data-in-pandas
        Note: This isn't a bottleneck. Using a feature set with 13k rows and 256
        data_frame ('ge' from 1962 until now), the normalization was immediate.

def transform(data_frame, **kwargs):
    """
    Return a transformed DataFrame.

    Transform data_frame along the given axis. By default, each row will be normalized (axis=0).

    Parameters
    -----------
    data_frame : DataFrame
        Data to be normalized.
    axis : int, optional
        0 (default) to normalize each row, 1 to normalize each column.
    method : str, optional
        Valid methods are:
        
        -  "vector" : Default for normalization by row (axis=0).
           Normalize along axis as a vector with norm `norm`
        -  "last" : Linear normalization setting last value along the axis to `norm`
        -  "first" : Default for normalization of columns (axis=1).
           Linear normalization setting first value along the given axis to `norm`
        -  "mean" : Normalize so that the mean of each vector along the given axis is `norm`
    norm : float, optional
        Target value of normalization, defaults to 1.0.
    labels : DataFrame, optional
        Labels may be passed as keyword argument, in which
        case the label values will also be normalized and returned.

    Returns
    -----------
    df : DataFrame
        Normalized data.
    labels : DataFrame, optional
        Normalized labels, if provided as input.

    Notes
    -----------
    If labels are real-valued, they should also be normalized.

    ..
        Having row_norms as a numpy array should be benchmarked against 
        using a DataFrame:
        http://stackoverflow.com/questions/12525722/normalize-data-in-pandas
        Note: This isn't a bottleneck. Using a feature set with 13k rows and 256
        data_frame ('ge' from 1962 until now), the normalization was immediate.
    """
    norm = kwargs.get('norm', 1.0)
    axis = kwargs.get('axis', 0)
    if axis == 0:
        norm_vector = _get_norms_of_rows(data_frame, kwargs.get('method', 'vector'))
    else:
        norm_vector = _get_norms_of_cols(data_frame, kwargs.get('method', 'first'))

    if 'labels' in kwargs:
        if axis == 0:
            return data_frame.apply(lambda col: col * norm / norm_vector, axis=0), \
                    kwargs['labels'].apply(lambda col: col * norm / norm_vector, axis=0)
        else:
            raise ValueError("label normalization incompatible with normalization by column")
    else:
        if axis == 0:
            return data_frame.apply(lambda col: col * norm / norm_vector, axis=0)
        else:
            return data_frame.apply(lambda row: row * norm / norm_vector, axis=1)