Crosstab calculation in R

How to Create a Crosstab in R (Cross Tabulation Guide with Examples)

Cross-tabulation, commonly known as a crosstab, is one of the most widely used techniques in statistics, data analysis, business intelligence, and survey research. A crosstab allows you to summarize the relationship between two categorical variables by displaying their frequencies in a matrix format.

In R, crosstabs can be created using several methods, but the combination of dplyr and tidyr provides a flexible and modern approach that integrates seamlessly with the tidyverse ecosystem.

In this tutorial, you’ll learn:

  • What a crosstab is
  • How to create crosstabs using dplyr and tidyr
  • How to customize rows and columns
  • Alternative methods using table() and xtabs()
  • Real-world applications of cross-tabulation
  • Best practices for analyzing categorical data

What Is a Crosstab?

A crosstab (cross-tabulation table) summarizes the frequency distribution of two or more categorical variables.

For example, a crosstab can answer questions such as:

  • How many employees belong to each department and gender?
  • How many customers fall into each age group and region?
  • How many players occupy different positions on each team?
  • How many survey respondents selected each response category?

Cross-tabulation is commonly used in:

  • Market research
  • Survey analysis
  • Business analytics
  • Healthcare studies
  • Social science research
  • Quality control

Basic Syntax for Creating a Crosstab in R

Using dplyr and tidyr, the basic syntax is:

df %>%
  group_by(var1, var2) %>%
  tally() %>%
  spread(var1, n)

This:

  1. Groups observations by two variables.
  2. Counts the number of occurrences.
  3. Reshapes the output into a crosstab format.

Example 1: Create a Simple Crosstab

Create a Sample Dataset

df <- data.frame(
  team = c("X", "X", "X", "X",
           "Y", "Y", "Y", "Y"),
  position = c("A", "A", "B", "C",
               "C", "C", "D", "D"),
  points = c(107, 207, 208, 211,
             213, 215, 219, 313)
)

df

Output:

  team position points
1    X        A    107
2    X        A    207
3    X        B    208
4    X        C    211
5    Y        C    213
6    Y        C    215
7    Y        D    219
8    Y        D    313

Load Required Packages

library(dplyr)
library(tidyr)

Generate the Crosstab

df %>%
  group_by(team, position) %>%
  tally() %>%
  spread(team, n)

Output:

# A tibble: 4 × 3

  position     X     Y
  <chr>    <int> <int>
1 A            2    NA
2 B            1    NA
3 C            1     2
4 D           NA     2

Interpreting the Crosstab

The table shows the frequency of each position within each team.

Team X

PositionCount
A2
B1
C1

Team Y

PositionCount
C2
D2

For example:

  • Team X has two players in Position A.
  • Team X has one player in Position B.
  • Team Y has two players in Position D.

Replace Missing Values with Zero

The default output displays missing combinations as NA.

Many analysts prefer displaying zeros instead.

df %>%
  group_by(team, position) %>%
  tally() %>%
  spread(team, n, fill = 0)

Output:

  position X Y
1 A        2 0
2 B        1 0
3 C        1 2
4 D        0 2

This format is often easier to interpret.

Example 2: Switch Rows and Columns

You can easily reverse the layout by changing the variable used in spread().

df %>%
  group_by(team, position) %>%
  tally() %>%
  spread(position, n)

Output:

  team   A   B   C   D
1 X     2   1   1  NA
2 Y    NA  NA   2   2

Adding fill = 0 produces:

df %>%
  group_by(team, position) %>%
  tally() %>%
  spread(position, n, fill = 0)

Output:

  team A B C D
1 X    2 1 1 0
2 Y    0 0 2 2

Modern Alternative: Using pivot_wider()

The spread() function has been superseded by pivot_wider() in newer versions of tidyr.

Recommended syntax:

df %>%
  count(team, position) %>%
  pivot_wider(
    names_from = team,
    values_from = n,
    values_fill = 0
  )

This approach is more flexible and future-proof.

Alternative Method Using table()

For quick cross-tabulations, base R provides the table() function.

table(df$position, df$team)

Output:

     X Y
A    2 0
B    1 0
C    1 2
D    0 2

This is often the fastest way to create a frequency table.

Alternative Method Using xtabs()

The xtabs() function is useful for statistical modeling and contingency tables.

xtabs(~ position + team, data = df)

Output:

         team
position  X Y
       A  2 0
       B  1 0
       C  1 2
       D  0 2

Calculate Row Percentages

Sometimes percentages are more informative than raw counts.

tab <- table(df$position, df$team)

prop.table(tab, margin = 1)

This calculates row-wise percentages.

Calculate Column Percentages

prop.table(tab, margin = 2)

This calculates percentages within each team.

Real-World Applications of Crosstabs

Business Intelligence

  • Customer segments by region
  • Product categories by sales channel

Marketing Analytics

  • Campaign performance by customer group
  • Conversion rates by traffic source

Human Resources

  • Employees by department and gender
  • Training participation by job role

Healthcare Analytics

  • Disease prevalence by age group
  • Treatment outcomes by patient category

Survey Research

  • Responses by demographic groups
  • Opinion analysis

Common Mistakes

Using Numerical Variables Directly

Crosstabs are designed primarily for categorical variables.

If needed, convert numeric variables into categories first.

Ignoring Missing Values

Missing categories can distort results.

Always inspect your data:

summary(df)

Not Replacing NA Values

Using:

fill = 0

often improves readability.

Best Practices

  • Use categorical variables whenever possible.
  • Replace missing combinations with zeros.
  • Consider percentages in addition to frequencies.
  • Use pivot_wider() for modern tidyverse workflows.
  • Validate totals against the original dataset.

Conclusion

Cross-tabulation is one of the most valuable tools for exploring relationships between categorical variables. In R, you can create crosstabs easily using dplyr, tidyr, table(), or xtabs().

Whether you’re analyzing survey data, customer behavior, employee records, or business performance metrics, crosstabs provide a quick and intuitive way to summarize and interpret categorical data.

By mastering cross-tabulation techniques in R, you’ll be able to perform deeper exploratory data analysis and generate more meaningful insights from your datasets.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

eleven + six =