def clean_data(df):
    """
    Clean the dataset

    Args:
        df: (pandas.DatFrame) containing data to be cleaned
    Returns:
        df: (pandas.DataFrame) containing the cleaned dataset
    """

    try:
        # clean target labels
        categories = df.categories.str.split(";", expand=True)
        cat_names = categories.applymap(lambda x: x[:-2]).values
        categories = categories.applymap(lambda x: x[-1])
        categories.columns = cat_names.tolist()[0]
        single_cardinality_classes = categories.columns[categories.nunique() == 1]
        categories.drop(single_cardinality_classes, axis=1, inplace=True)

        # drop original categories column
        df.drop(['categories'], axis=1, inplace=True)

        # convert categories columns to int
        for col in categories.columns:
            categories[col] = categories[col].astype(int)

        # convert categories.related values (2) to (1)
        categories.related = categories.related.replace(2, 1)

        # merge categories with df
        df = df.merge(categories, left_index=True, right_index=True)

        # drop duplicates
        df = df.drop_duplicates().reset_index(drop=True)

        # remove original columns as it is not needed for modelling
        df.drop(['original'], axis=1, inplace=True)
    except:
        raise Exception("Could not clean dataset.")
    finally:
        return df