Return DataFrame with duplicate rows (excluding index) removed,
        optionally only considering subset columns.

        Note that the row order is NOT maintained due to hashing.

        Parameters
        ----------
        subset : list of str, optional
            Which columns to consider
        keep : {'+', '*', 'min', 'max'}, optional
            What to select from the duplicate rows. These correspond to the possible merge operations in Weld.
            Note that '+' and '-' might produce unexpected results for strings.

        Returns
        -------
        DataFrame
            DataFrame without duplicate rows.

def drop_duplicates(self, subset=None, keep='min'):
        """Return DataFrame with duplicate rows (excluding index) removed,
        optionally only considering subset columns.

        Note that the row order is NOT maintained due to hashing.

        Parameters
        ----------
        subset : list of str, optional
            Which columns to consider
        keep : {'+', '*', 'min', 'max'}, optional
            What to select from the duplicate rows. These correspond to the possible merge operations in Weld.
            Note that '+' and '-' might produce unexpected results for strings.

        Returns
        -------
        DataFrame
            DataFrame without duplicate rows.

        """
        subset = check_and_obtain_subset_columns(subset, self)

        df = self.reset_index()
        df_names = df._gather_column_names()
        subset_indices = [df_names.index(col_name) for col_name in subset]

        weld_objects = weld_drop_duplicates(df._gather_data_for_weld(),
                                            df._gather_weld_types(),
                                            subset_indices,
                                            keep)

        index_data = self.index._gather_data(name=None)
        new_index = [Index(weld_objects[i], v.dtype, k)
                     for i, k, v in zip(list(range(len(index_data))), index_data.keys(), index_data.values())]
        if len(new_index) > 1:
            new_index = MultiIndex(new_index, self.index._gather_names())
        else:
            new_index = new_index[0]

        new_data = OrderedDict((sr.name, Series(obj, new_index, sr.dtype, sr.name))
                               for sr, obj in zip(self._iter(), weld_objects[len(index_data):]))

        return DataFrame(new_data, new_index)