def crosstab(data_index, data_column, code_index=None, code_column=None, qtype=None, total=True):
    "适用于问卷数据的交叉统计\n    输入参数：\n    data_index: 因变量，放在行中\n    data_column:自变量，放在列中\n    code_index: dict格式，指定data_index的编码等信息\n    code_column: dict格式，指定data_column的编码等信息\n    qtype: 给定两个数据的题目类型，若为字符串则给定data_index，若为列表，则给定两个的\n    返回字典格式数据\n    'fop'：默认的百分比表，行是data_index,列是data_column\n    'fo'：原始频数表，且添加了总体项\n    'fw': 加权平均值\n\n    简要说明：\n    因为要处理各类题型，这里将单选题处理为多选题\n\n    fo：观察频数表\n    nij是同时选择了Ri和Cj的频数\n    总体的频数是选择了Ri的频数，与所在行的总和无关\n    行变量\\列变量  C1 |C2 | C3| C4|总体\n             R1|  n11|n12|n13|n14|n1:\n             R2|  n21|n22|n23|n23|n2:\n             R3|  n31|n32|n33|n34|n3:\n     fop: 观察百分比表(列变量)\n     这里比较难处理，data_column各个类别的样本量和总体的样本量不一样，各类别的样本量为同时\n     选择了行变量和列类别的频数。而总体的样本量为选择了行变量的频数\n     fw: 加权平均值\n     如果data_index的编码code含有weight字段，则我们会输出分组的加权平均值\n\n\n    "
    data_index = pd.DataFrame(data_index)
    data_column = pd.DataFrame(data_column)
    if (data_index.shape[1] == 1):
        qtype1 = u'单选题'
    else:
        qtype1 = u'多选题'
    if (data_column.shape[1] == 1):
        qtype2 = u'单选题'
    else:
        qtype2 = u'多选题'
    if code_index:
        qtype1 = code_index['qtype']
        if (qtype1 == u'单选题'):
            data_index.replace(code_index['code'], inplace=True)
        elif (qtype1 in [u'多选题', u'排序题']):
            data_index.rename(columns=code_index['code'], inplace=True)
        elif (qtype1 == u'矩阵单选题'):
            data_index.rename(columns=code_index['code_r'], inplace=True)
    if code_column:
        qtype2 = code_column['qtype']
        if (qtype2 == u'单选题'):
            data_column.replace(code_column['code'], inplace=True)
        elif (qtype2 in [u'多选题', u'排序题']):
            data_column.rename(columns=code_column['code'], inplace=True)
        elif (qtype2 == u'矩阵单选题'):
            data_column.rename(columns=code_column['code_r'], inplace=True)
    if qtype:
        if (isinstance(qtype, list) and (len(qtype) == 2)):
            qtype1 = qtype[0]
            qtype2 = qtype[1]
        elif isinstance(qtype, str):
            qtype1 = qtype
    if (qtype1 == u'单选题'):
        data_index = sa_to_ma(data_index)
        qtype1 = u'多选题'
    if (qtype2 == u'单选题'):
        data_column = sa_to_ma(data_column)
        qtype2 = u'多选题'
    index_list = list(data_index.columns)
    columns_list = list(data_column.columns)
    column_freq = data_column.iloc[list(data_index.notnull().T.any()), :].sum()
    column_freq[u'总体'] = data_index.notnull().T.any().sum()
    R = len(index_list)
    C = len(columns_list)
    result = {}
    result['sample_size'] = column_freq
    if ((qtype1 == u'多选题') and (qtype2 == u'多选题')):
        data_index.fillna(0, inplace=True)
        t = pd.DataFrame(np.dot(data_index.fillna(0).T, data_column.fillna(0)))
        t.rename(index=dict(zip(range(R), index_list)), columns=dict(zip(range(C), columns_list)), inplace=True)
        if (code_index and ('weight' in code_index)):
            w = pd.Series(code_index['weight'])
            w.rename(index=code_index['code'], inplace=True)
            fw = pd.DataFrame(columns=[u'加权'], index=t.columns)
            for c in t.columns:
                tmp = t[c]
                tmp = tmp[w.index][tmp[w.index].notnull()]
                if (abs(tmp.sum()) > 0):
                    fw.loc[(c, u'加权')] = ((tmp * w).sum() / tmp.sum())
                else:
                    fw.loc[(c, u'加权')] = 0
            fo1 = data_index.sum()[w.index][data_index.sum()[w.index].notnull()]
            if (abs(fo1.sum()) > 0):
                fw.loc[(u'总体', u'加权')] = ((fo1 * w).sum() / fo1.sum())
            else:
                fw.loc[(u'总体', u'加权')] = 0
            result['fw'] = fw
        t[u'总体'] = data_index.sum()
        t.sort_values([u'总体'], ascending=False, inplace=True)
        t1 = t.copy()
        for i in t.columns:
            if (column_freq[i] != 0):
                t.loc[:, i] = (t.loc[:, i] / column_freq[i])
        result['fop'] = t
        result['fo'] = t1
    elif ((qtype1 == u'矩阵单选题') and (qtype2 == u'多选题')):
        if (code_index and ('weight' in code_index)):
            data_index.replace(code_index['weight'], inplace=True)
        t = pd.DataFrame(np.dot(data_index.fillna(0).T, data_column.fillna(0)))
        t = pd.DataFrame(np.dot(t, np.diag((1 / data_column.sum()))))
        t.rename(index=dict(zip(range(R), index_list)), columns=dict(zip(range(C), columns_list)), inplace=True)
        t[u'总体'] = data_index.mean()
        t.sort_values([u'总体'], ascending=False, inplace=True)
        t1 = t.copy()
        result['fop'] = t
        result['fo'] = t1
    elif ((qtype1 == u'排序题') and (qtype2 == u'多选题')):
        topn = int(data_index.max().max())
        qsort = dict(zip([(i + 1) for i in range(topn)], [((((topn - i) * 2.0) / (topn + 1)) / topn) for i in range(topn)]))
        data_index_zh = data_index.replace(qsort)
        t = pd.DataFrame(np.dot(data_index_zh.fillna(0).T, data_column.fillna(0)))
        t.rename(index=dict(zip(range(R), index_list)), columns=dict(zip(range(C), columns_list)), inplace=True)
        t[u'总体'] = data_index_zh.sum()
        t.sort_values([u'总体'], ascending=False, inplace=True)
        t1 = t.copy()
        for i in t.columns:
            if (column_freq[i] != 0):
                t.loc[:, i] = (t.loc[:, i] / column_freq[i])
        result['fop'] = t
        result['fo'] = t1
        data_index_top1 = data_index.applymap((lambda x: int((x == 1))))
        top1 = pd.DataFrame(np.dot(data_index_top1.fillna(0).T, data_column.fillna(0)))
        top1.rename(index=dict(zip(range(R), index_list)), columns=dict(zip(range(C), columns_list)), inplace=True)
        top1[u'总体'] = data_index_top1.fillna(0).sum()
        top1.sort_values([u'总体'], ascending=False, inplace=True)
        for i in top1.columns:
            if (column_freq[i] != 0):
                top1.loc[:, i] = (top1.loc[:, i] / column_freq[i])
        result['TOP1'] = top1
    else:
        result['fop'] = None
        result['fo'] = None
    if ((not total) and (not (result['fo'] is None)) and ('总体' in result['fo'].columns)):
        result['fo'].drop(['总体'], axis=1, inplace=True)
        result['fop'].drop(['总体'], axis=1, inplace=True)
    if ((not (result['fo'] is None)) and code_index and ('code_order' in code_index) and (qtype1 != '矩阵单选题')):
        code_order = code_index['code_order']
        code_order = [q for q in code_order if (q in result['fo'].index)]
        if (u'总体' in result['fo'].index):
            code_order = (code_order + [u'总体'])
        result['fo'] = pd.DataFrame(result['fo'], index=code_order)
        result['fop'] = pd.DataFrame(result['fop'], index=code_order)
    if ((not (result['fo'] is None)) and code_column and ('code_order' in code_column) and (qtype2 != '矩阵单选题')):
        code_order = code_column['code_order']
        code_order = [q for q in code_order if (q in result['fo'].columns)]
        if (u'总体' in result['fo'].columns):
            code_order = (code_order + [u'总体'])
        result['fo'] = pd.DataFrame(result['fo'], columns=code_order)
        result['fop'] = pd.DataFrame(result['fop'], columns=code_order)
    return result
适用于问卷数据的交叉统计
输入参数：
data_index: 因变量，放在行中
data_column:自变量，放在列中
code_index: dict格式，指定data_index的编码等信息
code_column: dict格式，指定data_column的编码等信息
qtype: 给定两个数据的题目类型，若为字符串则给定data_index，若为列表，则给定两个的
返回字典格式数据
'fop'：默认的百分比表，行是data_index,列是data_column
'fo'：原始频数表，且添加了总体项
'fw': 加权平均值

简要说明：
因为要处理各类题型，这里将单选题处理为多选题

fo：观察频数表
nij是同时选择了Ri和Cj的频数
总体的频数是选择了Ri的频数，与所在行的总和无关
行变量\列变量  C1 |C2 | C3| C4|总体
         R1|  n11|n12|n13|n14|n1:
         R2|  n21|n22|n23|n23|n2:
         R3|  n31|n32|n33|n34|n3:
 fop: 观察百分比表(列变量)
 这里比较难处理，data_column各个类别的样本量和总体的样本量不一样，各类别的样本量为同时
 选择了行变量和列类别的频数。而总体的样本量为选择了行变量的频数
 fw: 加权平均值
 如果data_index的编码code含有weight字段，则我们会输出分组的加权平均值
def crosstab(data_index, data_column, code_index=None, code_column=None, qtype=None, total=True):
    "适用于问卷数据的交叉统计\n    输入参数：\n    data_index: 因变量，放在行中\n    data_column:自变量，放在列中\n    code_index: dict格式，指定data_index的编码等信息\n    code_column: dict格式，指定data_column的编码等信息\n    qtype: 给定两个数据的题目类型，若为字符串则给定data_index，若为列表，则给定两个的\n    返回字典格式数据\n    'fop'：默认的百分比表，行是data_index,列是data_column\n    'fo'：原始频数表，且添加了总体项\n    'fw': 加权平均值\n\n    简要说明：\n    因为要处理各类题型，这里将单选题处理为多选题\n\n    fo：观察频数表\n    nij是同时选择了Ri和Cj的频数\n    总体的频数是选择了Ri的频数，与所在行的总和无关\n    行变量\\列变量  C1 |C2 | C3| C4|总体\n             R1|  n11|n12|n13|n14|n1:\n             R2|  n21|n22|n23|n23|n2:\n             R3|  n31|n32|n33|n34|n3:\n     fop: 观察百分比表(列变量)\n     这里比较难处理，data_column各个类别的样本量和总体的样本量不一样，各类别的样本量为同时\n     选择了行变量和列类别的频数。而总体的样本量为选择了行变量的频数\n     fw: 加权平均值\n     如果data_index的编码code含有weight字段，则我们会输出分组的加权平均值\n\n\n    "
    data_index = pd.DataFrame(data_index)
    data_column = pd.DataFrame(data_column)
    if (data_index.shape[1] == 1):
        qtype1 = u'单选题'
    else:
        qtype1 = u'多选题'
    if (data_column.shape[1] == 1):
        qtype2 = u'单选题'
    else:
        qtype2 = u'多选题'
    if code_index:
        qtype1 = code_index['qtype']
        if (qtype1 == u'单选题'):
            data_index.replace(code_index['code'], inplace=True)
        elif (qtype1 in [u'多选题', u'排序题']):
            data_index.rename(columns=code_index['code'], inplace=True)
        elif (qtype1 == u'矩阵单选题'):
            data_index.rename(columns=code_index['code_r'], inplace=True)
    if code_column:
        qtype2 = code_column['qtype']
        if (qtype2 == u'单选题'):
            data_column.replace(code_column['code'], inplace=True)
        elif (qtype2 in [u'多选题', u'排序题']):
            data_column.rename(columns=code_column['code'], inplace=True)
        elif (qtype2 == u'矩阵单选题'):
            data_column.rename(columns=code_column['code_r'], inplace=True)
    if qtype:
        if (isinstance(qtype, list) and (len(qtype) == 2)):
            qtype1 = qtype[0]
            qtype2 = qtype[1]
        elif isinstance(qtype, str):
            qtype1 = qtype
    if (qtype1 == u'单选题'):
        data_index = sa_to_ma(data_index)
        qtype1 = u'多选题'
    if (qtype2 == u'单选题'):
        data_column = sa_to_ma(data_column)
        qtype2 = u'多选题'
    index_list = list(data_index.columns)
    columns_list = list(data_column.columns)
    column_freq = data_column.iloc[list(data_index.notnull().T.any()), :].sum()
    column_freq[u'总体'] = data_index.notnull().T.any().sum()
    R = len(index_list)
    C = len(columns_list)
    result = {}
    result['sample_size'] = column_freq
    if ((qtype1 == u'多选题') and (qtype2 == u'多选题')):
        data_index.fillna(0, inplace=True)
        t = pd.DataFrame(np.dot(data_index.fillna(0).T, data_column.fillna(0)))
        t.rename(index=dict(zip(range(R), index_list)), columns=dict(zip(range(C), columns_list)), inplace=True)
        if (code_index and ('weight' in code_index)):
            w = pd.Series(code_index['weight'])
            w.rename(index=code_index['code'], inplace=True)
            fw = pd.DataFrame(columns=[u'加权'], index=t.columns)
            for c in t.columns:
                tmp = t[c]
                tmp = tmp[w.index][tmp[w.index].notnull()]
                if (abs(tmp.sum()) > 0):
                    fw.loc[(c, u'加权')] = ((tmp * w).sum() / tmp.sum())
                else:
                    fw.loc[(c, u'加权')] = 0
            fo1 = data_index.sum()[w.index][data_index.sum()[w.index].notnull()]
            if (abs(fo1.sum()) > 0):
                fw.loc[(u'总体', u'加权')] = ((fo1 * w).sum() / fo1.sum())
            else:
                fw.loc[(u'总体', u'加权')] = 0
            result['fw'] = fw
        t[u'总体'] = data_index.sum()
        t.sort_values([u'总体'], ascending=False, inplace=True)
        t1 = t.copy()
        for i in t.columns:
            if (column_freq[i] != 0):
                t.loc[:, i] = (t.loc[:, i] / column_freq[i])
        result['fop'] = t
        result['fo'] = t1
    elif ((qtype1 == u'矩阵单选题') and (qtype2 == u'多选题')):
        if (code_index and ('weight' in code_index)):
            data_index.replace(code_index['weight'], inplace=True)
        t = pd.DataFrame(np.dot(data_index.fillna(0).T, data_column.fillna(0)))
        t = pd.DataFrame(np.dot(t, np.diag((1 / data_column.sum()))))
        t.rename(index=dict(zip(range(R), index_list)), columns=dict(zip(range(C), columns_list)), inplace=True)
        t[u'总体'] = data_index.mean()
        t.sort_values([u'总体'], ascending=False, inplace=True)
        t1 = t.copy()
        result['fop'] = t
        result['fo'] = t1
    elif ((qtype1 == u'排序题') and (qtype2 == u'多选题')):
        topn = int(data_index.max().max())
        qsort = dict(zip([(i + 1) for i in range(topn)], [((((topn - i) * 2.0) / (topn + 1)) / topn) for i in range(topn)]))
        data_index_zh = data_index.replace(qsort)
        t = pd.DataFrame(np.dot(data_index_zh.fillna(0).T, data_column.fillna(0)))
        t.rename(index=dict(zip(range(R), index_list)), columns=dict(zip(range(C), columns_list)), inplace=True)
        t[u'总体'] = data_index_zh.sum()
        t.sort_values([u'总体'], ascending=False, inplace=True)
        t1 = t.copy()
        for i in t.columns:
            if (column_freq[i] != 0):
                t.loc[:, i] = (t.loc[:, i] / column_freq[i])
        result['fop'] = t
        result['fo'] = t1
        data_index_top1 = data_index.applymap((lambda x: int((x == 1))))
        top1 = pd.DataFrame(np.dot(data_index_top1.fillna(0).T, data_column.fillna(0)))
        top1.rename(index=dict(zip(range(R), index_list)), columns=dict(zip(range(C), columns_list)), inplace=True)
        top1[u'总体'] = data_index_top1.fillna(0).sum()
        top1.sort_values([u'总体'], ascending=False, inplace=True)
        for i in top1.columns:
            if (column_freq[i] != 0):
                top1.loc[:, i] = (top1.loc[:, i] / column_freq[i])
        result['TOP1'] = top1
    else:
        result['fop'] = None
        result['fo'] = None
    if ((not total) and (not (result['fo'] is None)) and ('总体' in result['fo'].columns)):
        result['fo'].drop(['总体'], axis=1, inplace=True)
        result['fop'].drop(['总体'], axis=1, inplace=True)
    if ((not (result['fo'] is None)) and code_index and ('code_order' in code_index) and (qtype1 != '矩阵单选题')):
        code_order = code_index['code_order']
        code_order = [q for q in code_order if (q in result['fo'].index)]
        if (u'总体' in result['fo'].index):
            code_order = (code_order + [u'总体'])
        result['fo'] = pd.DataFrame(result['fo'], index=code_order)
        result['fop'] = pd.DataFrame(result['fop'], index=code_order)
    if ((not (result['fo'] is None)) and code_column and ('code_order' in code_column) and (qtype2 != '矩阵单选题')):
        code_order = code_column['code_order']
        code_order = [q for q in code_order if (q in result['fo'].columns)]
        if (u'总体' in result['fo'].columns):
            code_order = (code_order + [u'总体'])
        result['fo'] = pd.DataFrame(result['fo'], columns=code_order)
        result['fop'] = pd.DataFrame(result['fop'], columns=code_order)
    return result