def clean_data(df):
    """Clean the loaded messages and categories data.
     Convert 'categories' column string into a set of numeric columns, and remove duplicate rows.

     Arg:
      - df: DataFrame containing data loaded by load_data()

     Returns:
      - DataFrame of cleaned data.
     """
    # Categories are in a single string column; create a dataframe with a column for each category
    categories = df.categories.str.split(';', expand=True)

    # select the first row of the categories dataframe
    row = categories.iloc[0]
    # use this row to extract a list of new column names for categories.
    category_colnames = [s[:-2] for s in row]
    # rename the columns of `categories`
    categories.columns = category_colnames

    # convert category values to numbers
    for column in categories:
        # set each value to be the last character of the string
        categories[column] = categories[column].str[-1]

        # convert column from string to numeric
        categories[column] = categories[column].astype(int)

    # related column has values (0, 1, 2)
    # encode all non-related entries as 0, so we have 1 for related, 0 for non-related
    categories.related = categories.related.replace(2, 0)

    # replace original category string values with numeric columns
    df = df.drop('categories', axis=1)

    # concatenate the original dataframe with the new `categories` dataframe
    df = df.join(categories)

    # remove duplicates
    return df.drop_duplicates()