def partition_data(df, partition_by):
    """Partition data by values found in one or more columns.

    For each of the selected columns the unique values will
    be determined and a selection will be made for each element
    in the cross product of the unique values.

    Parameters
    ----------
    df : pandas.DataFrame
        Data to be partitioned

    partition_by : list
        Column names to partition by

    Returns
    -------
    dict
        Partition dictionary with keys:

        * labels : Tuple of dictionaries whose keys are the column names
                   and values are the actual values in the column
        * data   : Tuple of pandas.DataFrame objects holding the subset of the data with
    """
    labels = []
    data = []

    for key, group in df.groupby(partition_by):
        if not isinstance(key, tuple):
            key = (key,)
        labels.append(dict(zip(partition_by, key)))
        data.append(group.drop(partition_by, axis=1))
    return {"labels": tuple(labels), "data": tuple(data)}