<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _drop(expr, data, axis=0, columns=None):
 """ Drop data from a DataFrame. :param expr: collection to drop data from :param data: data to be removed :param axis: 0 for deleting rows, 1 for columns. :param columns: columns of data to select, only useful when axis == 0 :return: collection :Example: a b c 0 1 4 7 1 3 6 9 a b c 0 1 4 7 b c 0 4 7 1 5 8 2 6 9 c 0 7 1 8 2 9 """

    from ..utils import to_collection
    expr = to_collection(expr)

    if axis == 0:
        if not isinstance(data, (CollectionExpr, SequenceExpr)):
            raise ExpressionError('data should be a collection or sequence when axis == 1.')

        data = to_collection(data)
        if columns is None:
            columns = [n for n in data.schema.names]
        if isinstance(columns, six.string_types):
            columns = [columns, ]

        data = data.select(*columns).distinct()

        drop_predicates = [data[n].isnull() for n in data.schema.names]
        return expr.left_join(data, on=columns, suffixes=('', '_dp')).filter(*drop_predicates) \
            .select(*expr.schema.names)
    else:
        if isinstance(data, (CollectionExpr, SequenceExpr)):
            data = to_collection(data).schema.names
        return expr.exclude(data)