def impute(self, vars: dict, replace: bool=False, prefix: str='imp_', out: 'SASdata'=None) -> 'SASdata':
    "\n        Imputes missing values for a SASdata object.\n\n        :param vars: a dictionary in the form of {'varname':'impute type'} or {'impute type':'[var1, var2]'}\n        :param replace:\n        :param prefix:\n        :param out:\n        :return:\n        "
    outstr = ''
    if out:
        if isinstance(out, str):
            fn = out.partition('.')
            if (fn[1] == '.'):
                out_libref = fn[0]
                out_table = fn[2]
            else:
                out_libref = ''
                out_table = fn[0]
        else:
            out_libref = out.libref
            out_table = out.table
        outstr = ('out=%s.%s' % (out_libref, out_table))
    else:
        out_table = self.table
        out_libref = self.libref
    varcode = (((("data _null_; d = open('" + self.libref) + '.') + self.table) + "');\n")
    varcode += "nvars = attrn(d, 'NVARS');\n"
    varcode += "put 'VARNUMS=' nvars 'VARNUMS_END=';\n"
    varcode += "put 'VARLIST=';\n"
    varcode += "do i = 1 to nvars; var = varname(d, i); put %upcase('var=') var %upcase('varEND='); end;\n"
    varcode += "put 'TYPELIST=';\n"
    varcode += "do i = 1 to nvars; var = vartype(d, i); put %upcase('type=') var %upcase('typeEND='); end;\n"
    varcode += "put 'END_ALL_VARS_AND_TYPES=';\n"
    varcode += 'run;'
    ll = self.sas._io.submit(varcode, 'text')
    l2 = ll['LOG'].rpartition('VARNUMS=')[2].partition('VARNUMS_END=')
    nvars = int(float(l2[0].strip()))
    varlist = []
    log = ll['LOG'].rpartition('TYPELIST=')[0].rpartition('VARLIST=')
    for vari in range(log[2].count('VAR=')):
        log = log[2].partition('VAR=')[2].partition('VAREND=')
        varlist.append(log[0].strip().upper())
    typelist = []
    log = ll['LOG'].rpartition('END_ALL_VARS_AND_TYPES=')[0].rpartition('TYPELIST=')
    for typei in range(log[2].count('VAR=')):
        log = log[2].partition('TYPE=')[2].partition('TYPEEND=')
        typelist.append(log[0].strip().upper())
    varListType = dict(zip(varlist, typelist))
    sql = 'proc sql;\n  select\n'
    sqlsel = ' %s(%s),\n'
    sqlinto = ' into\n'
    if (len(out_libref) > 0):
        ds1 = ((((((((('data ' + out_libref) + '.') + out_table) + '; set ') + self.libref) + '.') + self.table) + self._dsopts()) + ';\n')
    else:
        ds1 = ((((((('data ' + out_table) + '; set ') + self.libref) + '.') + self.table) + self._dsopts()) + ';\n')
    dsmiss = 'if missing({0}) then {1} = {2};\n'
    if replace:
        dsmiss = (prefix + ('{1} = {0}; if missing({0}) then %s{1} = {2};\n' % prefix))
    modesql = ''
    modeq = 'proc sql outobs=1;\n  select %s, count(*) as freq into :imp_mode_%s, :imp_mode_freq\n'
    modeq += '  from %s where %s is not null group by %s order by freq desc, %s;\nquit;\n'
    contantValues = vars.pop('value', None)
    if (contantValues is not None):
        if (not all((isinstance(x, tuple) for x in contantValues))):
            raise SyntaxError("The elements in the 'value' key must be tuples")
        for t in contantValues:
            if (varListType.get(t[0].upper()) == 'N'):
                ds1 += dsmiss.format((t[0], t[0], t[1]))
            else:
                ds1 += dsmiss.format(t[0], t[0], (('"' + str(t[1])) + '"'))
    for (key, values) in vars.items():
        if (key.lower() in ['midrange', 'random']):
            for v in values:
                sql += (sqlsel % ('max', v))
                sql += (sqlsel % ('min', v))
                sqlinto += ((' :imp_max_' + v) + ',\n')
                sqlinto += ((' :imp_min_' + v) + ',\n')
                if (key.lower() == 'midrange'):
                    ds1 += dsmiss.format(v, v, ((((((('(&imp_min_' + v) + '.') + ' + ') + '&imp_max_') + v) + '.') + ') / 2'))
                elif (key.lower() == 'random'):
                    ds1 += dsmiss.format(v, v, (((((((((('(&imp_max_' + v) + '.') + ' - ') + '&imp_min_') + v) + '.') + ') * ranuni(0)') + '+ &imp_min_') + v) + '.'))
                else:
                    raise SyntaxError('This should not happen!!!!')
        else:
            for v in values:
                sql += (sqlsel % (key, v))
                sqlinto += ((' :imp_' + v) + ',\n')
                if (key.lower == 'mode'):
                    modesql += (modeq % (v, v, (((self.libref + '.') + self.table) + self._dsopts()), v, v, v))
                if (varListType.get(v.upper()) == 'N'):
                    ds1 += dsmiss.format(v, v, (('&imp_' + v) + '.'))
                else:
                    ds1 += dsmiss.format(v, v, (('"&imp_' + v) + '."'))
    if (len(sql) > 20):
        sql = ((((((((sql.rstrip(', \n') + '\n') + sqlinto.rstrip(', \n')) + '\n  from ') + self.libref) + '.') + self.table) + self._dsopts()) + ';\nquit;\n')
    else:
        sql = ''
    ds1 += 'run;\n'
    if self.sas.nosub:
        print(((modesql + sql) + ds1))
        return None
    ll = self.sas.submit(((modesql + sql) + ds1))
    return self.sas.sasdata(out_table, libref=out_libref, results=self.results, dsopts=self._dsopts())
Imputes missing values for a SASdata object.

:param vars: a dictionary in the form of {'varname':'impute type'} or {'impute type':'[var1, var2]'}
:param replace:
:param prefix:
:param out:
:return:
def impute(self, vars: dict, replace: bool=False, prefix: str='imp_', out: 'SASdata'=None) -> 'SASdata':
    "\n        Imputes missing values for a SASdata object.\n\n        :param vars: a dictionary in the form of {'varname':'impute type'} or {'impute type':'[var1, var2]'}\n        :param replace:\n        :param prefix:\n        :param out:\n        :return:\n        "
    outstr = 
    if out:
        if isinstance(out, str):
            fn = out.partition('.')
            if (fn[1] == '.'):
                out_libref = fn[0]
                out_table = fn[2]
            else:
                out_libref = 
                out_table = fn[0]
        else:
            out_libref = out.libref
            out_table = out.table
        outstr = ('out=%s.%s' % (out_libref, out_table))
    else:
        out_table = self.table
        out_libref = self.libref
    varcode = (((("data _null_; d = open('" + self.libref) + '.') + self.table) + "');\n")
    varcode += "nvars = attrn(d, 'NVARS');\n"
    varcode += "put 'VARNUMS=' nvars 'VARNUMS_END=';\n"
    varcode += "put 'VARLIST=';\n"
    varcode += "do i = 1 to nvars; var = varname(d, i); put %upcase('var=') var %upcase('varEND='); end;\n"
    varcode += "put 'TYPELIST=';\n"
    varcode += "do i = 1 to nvars; var = vartype(d, i); put %upcase('type=') var %upcase('typeEND='); end;\n"
    varcode += "put 'END_ALL_VARS_AND_TYPES=';\n"
    varcode += 'run;'
    ll = self.sas._io.submit(varcode, 'text')
    l2 = ll['LOG'].rpartition('VARNUMS=')[2].partition('VARNUMS_END=')
    nvars = int(float(l2[0].strip()))
    varlist = []
    log = ll['LOG'].rpartition('TYPELIST=')[0].rpartition('VARLIST=')
    for vari in range(log[2].count('VAR=')):
        log = log[2].partition('VAR=')[2].partition('VAREND=')
        varlist.append(log[0].strip().upper())
    typelist = []
    log = ll['LOG'].rpartition('END_ALL_VARS_AND_TYPES=')[0].rpartition('TYPELIST=')
    for typei in range(log[2].count('VAR=')):
        log = log[2].partition('TYPE=')[2].partition('TYPEEND=')
        typelist.append(log[0].strip().upper())
    varListType = dict(zip(varlist, typelist))
    sql = 'proc sql;\n  select\n'
    sqlsel = ' %s(%s),\n'
    sqlinto = ' into\n'
    if (len(out_libref) > 0):
        ds1 = ((((((((('data ' + out_libref) + '.') + out_table) + '; set ') + self.libref) + '.') + self.table) + self._dsopts()) + ';\n')
    else:
        ds1 = ((((((('data ' + out_table) + '; set ') + self.libref) + '.') + self.table) + self._dsopts()) + ';\n')
    dsmiss = 'if missing({0}) then {1} = {2};\n'
    if replace:
        dsmiss = (prefix + ('{1} = {0}; if missing({0}) then %s{1} = {2};\n' % prefix))
    modesql = 
    modeq = 'proc sql outobs=1;\n  select %s, count(*) as freq into :imp_mode_%s, :imp_mode_freq\n'
    modeq += '  from %s where %s is not null group by %s order by freq desc, %s;\nquit;\n'
    contantValues = vars.pop('value', None)
    if (contantValues is not None):
        if (not all((isinstance(x, tuple) for x in contantValues))):
            raise SyntaxError("The elements in the 'value' key must be tuples")
        for t in contantValues:
            if (varListType.get(t[0].upper()) == 'N'):
                ds1 += dsmiss.format((t[0], t[0], t[1]))
            else:
                ds1 += dsmiss.format(t[0], t[0], (('"' + str(t[1])) + '"'))
    for (key, values) in vars.items():
        if (key.lower() in ['midrange', 'random']):
            for v in values:
                sql += (sqlsel % ('max', v))
                sql += (sqlsel % ('min', v))
                sqlinto += ((' :imp_max_' + v) + ',\n')
                sqlinto += ((' :imp_min_' + v) + ',\n')
                if (key.lower() == 'midrange'):
                    ds1 += dsmiss.format(v, v, ((((((('(&imp_min_' + v) + '.') + ' + ') + '&imp_max_') + v) + '.') + ') / 2'))
                elif (key.lower() == 'random'):
                    ds1 += dsmiss.format(v, v, (((((((((('(&imp_max_' + v) + '.') + ' - ') + '&imp_min_') + v) + '.') + ') * ranuni(0)') + '+ &imp_min_') + v) + '.'))
                else:
                    raise SyntaxError('This should not happen!!!!')
        else:
            for v in values:
                sql += (sqlsel % (key, v))
                sqlinto += ((' :imp_' + v) + ',\n')
                if (key.lower == 'mode'):
                    modesql += (modeq % (v, v, (((self.libref + '.') + self.table) + self._dsopts()), v, v, v))
                if (varListType.get(v.upper()) == 'N'):
                    ds1 += dsmiss.format(v, v, (('&imp_' + v) + '.'))
                else:
                    ds1 += dsmiss.format(v, v, (('"&imp_' + v) + '."'))
    if (len(sql) > 20):
        sql = ((((((((sql.rstrip(', \n') + '\n') + sqlinto.rstrip(', \n')) + '\n  from ') + self.libref) + '.') + self.table) + self._dsopts()) + ';\nquit;\n')
    else:
        sql = 
    ds1 += 'run;\n'
    if self.sas.nosub:
        print(((modesql + sql) + ds1))
        return None
    ll = self.sas.submit(((modesql + sql) + ds1))
    return self.sas.sasdata(out_table, libref=out_libref, results=self.results, dsopts=self._dsopts())