def crosstab(index, columns, values=None, rownames=None, colnames=None,<EOL>aggfunc=None, margins=False, margins_name='<STR_LIT>', dropna=True,<EOL>normalize=False):
index = com.maybe_make_list(index)<EOL>columns = com.maybe_make_list(columns)<EOL>rownames = _get_names(index, rownames, prefix='<STR_LIT>')<EOL>colnames = _get_names(columns, colnames, prefix='<STR_LIT>')<EOL>common_idx = _get_objs_combined_axis(index + columns, intersect=True,<EOL>sort=False)<EOL>data = {}<EOL>data.update(zip(rownames, index))<EOL>data.update(zip(colnames, columns))<EOL>if values is None and aggfunc is not None:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>if values is not None and aggfunc is None:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>from pandas import DataFrame<EOL>df = DataFrame(data, index=common_idx)<EOL>if values is None:<EOL><INDENT>df['<STR_LIT>'] = <NUM_LIT:0><EOL>kwargs = {'<STR_LIT>': len, '<STR_LIT>': <NUM_LIT:0>}<EOL><DEDENT>else:<EOL><INDENT>df['<STR_LIT>'] = values<EOL>kwargs = {'<STR_LIT>': aggfunc}<EOL><DEDENT>table = df.pivot_table('<STR_LIT>', index=rownames, columns=colnames,<EOL>margins=margins, margins_name=margins_name,<EOL>dropna=dropna, **kwargs)<EOL>if normalize is not False:<EOL><INDENT>table = _normalize(table, normalize=normalize, margins=margins,<EOL>margins_name=margins_name)<EOL><DEDENT>return table<EOL>
Compute a simple cross tabulation of two (or more) factors. By default
computes a frequency table of the factors unless an array of values and an
aggregation function are passed.

Parameters
----------
index : array-like, Series, or list of arrays/Series
    Values to group by in the rows.
columns : array-like, Series, or list of arrays/Series
    Values to group by in the columns.
values : array-like, optional
    Array of values to aggregate according to the factors.
    Requires `aggfunc` be specified.
rownames : sequence, default None
    If passed, must match number of row arrays passed.
colnames : sequence, default None
    If passed, must match number of column arrays passed.
aggfunc : function, optional
    If specified, requires `values` be specified as well.
margins : bool, default False
    Add row/column margins (subtotals).
margins_name : str, default 'All'
    Name of the row/column that will contain the totals
    when margins is True.

    .. versionadded:: 0.21.0

dropna : bool, default True
    Do not include columns whose entries are all NaN.
normalize : bool, {'all', 'index', 'columns'}, or {0,1}, default False
    Normalize by dividing all values by the sum of values.

    - If passed 'all' or `True`, will normalize over all values.
    - If passed 'index' will normalize over each row.
    - If passed 'columns' will normalize over each column.
    - If margins is `True`, will also normalize margin values.

    .. versionadded:: 0.18.1

Returns
-------
DataFrame
    Cross tabulation of the data.

See Also
--------
DataFrame.pivot : Reshape data based on column values.
pivot_table : Create a pivot table as a DataFrame.

Notes
-----
Any Series passed will have their name attributes used unless row or column
names for the cross-tabulation are specified.

Any input passed containing Categorical data will have **all** of its
categories included in the cross-tabulation, even if the actual data does
not contain any instances of a particular category.

In the event that there aren't overlapping indexes an empty DataFrame will
be returned.

Examples
--------
>>> a = np.array(["foo", "foo", "foo", "foo", "bar", "bar",
...               "bar", "bar", "foo", "foo", "foo"], dtype=object)
>>> b = np.array(["one", "one", "one", "two", "one", "one",
...               "one", "two", "two", "two", "one"], dtype=object)
>>> c = np.array(["dull", "dull", "shiny", "dull", "dull", "shiny",
...               "shiny", "dull", "shiny", "shiny", "shiny"],
...              dtype=object)
>>> pd.crosstab(a, [b, c], rownames=['a'], colnames=['b', 'c'])
b   one        two
c   dull shiny dull shiny
a
bar    1     2    1     0
foo    2     2    1     2

Here 'c' and 'f' are not represented in the data and will not be
shown in the output because dropna is True by default. Set
dropna=False to preserve categories with no data.

>>> foo = pd.Categorical(['a', 'b'], categories=['a', 'b', 'c'])
>>> bar = pd.Categorical(['d', 'e'], categories=['d', 'e', 'f'])
>>> pd.crosstab(foo, bar)
col_0  d  e
row_0
a      1  0
b      0  1
>>> pd.crosstab(foo, bar, dropna=False)
col_0  d  e  f
row_0
a      1  0  0
b      0  1  0
c      0  0  0