<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def rebuild_schema(doc, r, df):
 """Rebuild the schema for a resource based on a dataframe"""

    import numpy as np

    # Re-get the resource in the doc, since it may be different.
    try:
        r = doc.resource(r.name)
    except AttributeError:
        # Maybe r is actually a resource name
        r = doc.resource(r)

    def alt_col_name(name, i):
        import re

        if not name:
            return 'col{}'.format(i)

        return re.sub('_+', '_', re.sub('[^\w_]', '_', str(name)).lower()).rstrip('_')

    df_types = {
        np.dtype('O'): 'text',
        np.dtype('int64'): 'integer',
        np.dtype('float64'): 'number'
    }

    try:
        df_index_frame = df.index.to_frame()
    except AttributeError:
        df_index_frame = None

    def get_col_dtype(c):

        c = str(c)

        try:
            return df_types[df[c].dtype]
        except KeyError:
            # Maybe it is in the index?
            pass

        try:
            return df_types[df_index_frame[c].dtype]
        except TypeError:
            # Maybe not a multi-index
            pass

        if c == 'id' or c == df.index.name:
            return df_types[df.index.dtype]

        return 'unknown'

    columns = []
    schema_term = r.schema_term[0]

    if schema_term:

        old_cols = {c['name'].value: c.properties for c in schema_term.children}
        for c in schema_term.children:
            schema_term.remove_child(c)

        schema_term.children = []

    else:
        old_cols = {}
        schema_term = doc['Schema'].new_term('Table', r.schema_name)

    index_names = [n if n else "id" for n in df.index.names]

    for i, col in enumerate(index_names + list(df.columns)):
        acn = alt_col_name(col, i) if alt_col_name(col, i) != str(col) else ''

        d = {'name': col, 'datatype': get_col_dtype(col), 'altname': acn}

        if col in old_cols.keys():
            lookup_name = col
        elif acn in old_cols.keys():
            lookup_name = acn
        else:
            lookup_name = None

        if lookup_name and lookup_name in old_cols:

            for k, v in schema_term.properties.items():

                old_col = old_cols.get(lookup_name)

                for k, v in old_col.items():
                    if k != 'name' and v:
                        d[k] = v

        columns.append(d)

    for c in columns:
        name = c['name']
        del c['name']
        datatype = c['datatype']
        del c['datatype']
        altname = c['altname']
        del c['altname']

        schema_term.new_child('Column', name, datatype=datatype, altname=altname, **c)