pd.crosstab counts how often each pair of values occurs, with one column's values down the side and the other's across the top:
pd.crosstab(df["region"], df["channel"])
It takes the columns themselves (Series), not their names, which is the one thing that trips people up coming from pivot_table.
normalize="index" turns each row into percentages that add up to 1 (what share of the North's orders were online?). "columns" does the same down each column, and "all" divides by the grand total.
margins=True adds an All row and column with totals.
values= and aggfunc= sum or average another column instead of counting, which makes it a pivot table.
Read the normalize option carefully: row percentages and column percentages answer different questions.