In RStudio, table() is an R function that counts how often each value or combination of values appears in one or more vectors. For example, run table(df$category) in the Console to get a frequency count; RStudio is the interface, while table() belongs to base R.
What table() does
The function summarizes categorical data by tallying observations. Given a vector of labels, it returns the number of times each distinct value occurs. With two or more vectors, it builds a cross-tabulation: counts for each combination of categories. Its result is an object of class table, represented as an array with dimensions and, usually, category names attached.
For instance, if a survey records each respondent’s preferred transport, this code counts responses:
transport <- c('bus', 'bike', 'bus', 'walk', 'bike', 'bus')
table(transport)
The result reports bus 3, bike 2, and walk 1. It is a compact summary, not a modified version of the original data: the input vector remains unchanged. The counts are useful for checking category balance, summarizing survey answers, and preparing contingency tables for further analysis.
Basic syntax and a first example
The common form is table(...), where the dots represent one or more vectors or factors. A one-variable table gives frequency counts; multiple arguments produce a multi-way table. When supplying multiple vectors, use vectors of the same length so each position describes the same observation.
Here is an example with a small data frame. The first vector identifies a department and the second records a response:
department <- c('Sales', 'Support', 'Sales', 'Support', 'Sales')
response <- c('Yes', 'No', 'Yes', 'Yes', 'No')
table(department)
The one-variable result has two department counts: Sales appears three times and Support appears twice. You can also type an expression directly at the Console prompt, or run the same code from an R script by selecting it and choosing Run. In either case, the printed result appears in the Console.
For actual data, a typical call is table(df$department). The dollar sign selects the named column from a data frame. If the column name contains spaces or punctuation, use backticks, as in table(df$`service type`). You can also pass a vector stored in a separate variable.
Missing values and unused categories
By default, missing values are not displayed as a category in the output. Use the useNA argument when you want them counted. Its options are 'no' (the default), 'ifany' (show a missing-value count when missing values occur), and 'always' (include that category even if its count is zero).
rating <- c('good', 'poor', NA, 'good')
table(rating, useNA = 'ifany')
This table shows good with a count of 2, poor with a count of 1, and an NA category with a count of 1. Counting missing entries is often important: a table that silently omits them can make the displayed category totals seem smaller than the number of rows in the source data. If missingness itself is meaningful, report it rather than treating it as an ordinary response without explanation.
Factors introduce another detail. A factor can have defined levels that do not occur in the observed data. Those levels can still appear in a table with a zero count. This is useful when you need consistent categories across reports or samples, but it can surprise readers who expect only observed values. A character vector generally displays the values present in that vector.
Reading two-way and multi-way tables
Pass two variables to compare their categories. Each cell in the result is the number of rows where both categories occur together:
table(department, response)
The first variable forms the rows and the second forms the columns. The row and column labels identify categories, and the cell values are counts. This is useful for questions such as “How many Sales respondents said Yes?” or “How many Support respondents said No?” The table does not, by itself, say whether a difference is statistically meaningful.
You can add a third variable, but the result then has three dimensions, and further variables add more. Multi-way tables can be useful for stratified summaries, but are harder to read in the Console. For a quick view of a two-variable table, use named columns:
table(df$department, df$response)
To give the dimensions clearer labels, set dnn, which supplies dimension names:
table(df$department, df$response,
dnn = c('Department', 'Response'))
For a standard frequency table, the total of all cells equals the number of included observations. It can be lower than the number of source rows when missing values are excluded by default. If you are checking a data-cleaning step, compare the table’s total with the expected row count and decide explicitly how missing entries should be handled.
Getting proportions and margins
Counts are not always the easiest way to compare groups of different sizes. The base R function prop.table() converts a table to proportions. With one variable, it divides each count by the overall total:
counts <- table(transport)
prop.table(counts)
The proportions sum to 1, subject to normal floating-point display. Multiply by 100 if you want percentages. For a two-way table, use the margin argument to calculate proportions within a dimension. With margin = 1, values are divided by their row totals; with margin = 2, they are divided by column totals. State which denominator you used, because row percentages and column percentages answer different questions.
To add row and column totals to a two-way table, use addmargins():
addmargins(table(department, response))
The added totals make it easier to check group sizes and grand totals. They do not replace the original cell counts; they add summary margins to the printed table.
Viewing or exporting the result in RStudio
For small tables, the Console output is often the clearest option. If you want a rectangular data-frame form for sorting, exporting, or viewing, wrap the table in as.data.frame():
result <- as.data.frame(table(department, response))
View(result)
The resulting data frame has columns for the categories and a Freq column for the count. In RStudio, View() opens the data viewer for this rectangular result. You can also export it with base R’s write.csv(), or use RStudio’s Export control in the data viewer where available. The original table and the converted data frame are different representations of the same counts; converting does not create additional observations.
Common problems and useful checks
- Unexpectedly small totals: Missing values are omitted by default. Try
useNA = 'ifany'and compare the result with the number of source rows. - Zero-count categories: Check whether an input is a factor with levels that are not observed. Such levels can be retained with zero counts.
- Misaligned variables: When two vectors come from different sources, confirm that their values still correspond row by row and have compatible lengths before tabulating them.
- Hard-to-read output: A table with many categories or dimensions can be unwieldy. Filter or recode categories for a focused summary, or convert the result to a data frame.
- Confusing counts with percentages:
table()returns counts. Useprop.table()for proportions and identify whether percentages use the whole sample, rows, or columns as the denominator.
A frequent misconception is that table() makes a spreadsheet-style table that can be edited in place. It produces a summary object in R. If you need a formatted report, you can convert it to a data frame and then use reporting or plotting tools; formatting is separate from counting.
How table() compares with related R tools
table() is a good choice for quick counts and cross-tabulations using base R, so it does not require an additional package. xtabs() is another base R option that uses a formula interface. For example, xtabs(~ department + response, data = df) expresses a two-way count in terms of columns in a data frame. It can feel natural when the variables already live in a data frame, while table(df$department, df$response) is direct and familiar for simple cases.
In a data-manipulation workflow, functions such as dplyr::count() can count combinations and return a data frame, but they require the dplyr package. Choose based on the output you need: use table() for a compact array of counts, as.data.frame(table(...)) for a base-R rectangular result, or a package workflow when you need to combine counting with other data transformations. These approaches summarize data; none automatically establishes that observed group differences have a particular cause.
Frequently Asked Questions
Is table() part of RStudio or R?table() is part of base R, not a special RStudio-only feature. RStudio provides an interface for writing and running R code, so the same function also works in other R environments.
How do I count values in a column in RStudio?
Use table(data$column), replacing data and column with your data-frame and column names. For example, table(df$category) prints the count for each category in the Console.
How do I include NA values in table()?
Set useNA = 'ifany' to display a missing-value count when missing values are present, or useNA = 'always' to include the NA category even when its count is zero. The default is to omit missing values from the displayed counts.
How do I make a two-way frequency table?
Pass both variables to the function, such as table(df$group, df$outcome). Rows correspond to the first variable and columns to the second; each cell counts observations with that combination.
How do I turn a table into a data frame?
Use as.data.frame(table(df$group, df$outcome)). The result has category columns and a Freq column, which is often easier to export or inspect with RStudio’s View().
Related
- Excel Named Ranges: Can They Cover Multiple Cells?
- Data Validation and Quality Assurance in Excel
- Power Query Remove Leading Zeros Without Losing IDs
Try it: the Date Difference Calculator: days, months, years and weekdays between two dates, with the DATEDIF formulas.
More in How-to basics
- Conditional Formatting for an Entire Row in Excel 365Yes. In Excel for Microsoft 365, you can conditionally format an entire row by selecting the rows to…
- Excel Cell Auto Adjust: How to Fit Width and Row HeightTo auto-adjust cells in Excel for Microsoft 365 on Windows, select the column or row, then double-click the…
- How to Find Duplicates in Excel Quickly and AccuratelyTo find duplicate values in Excel, select the cells you want to check, then choose Home > Conditional…
- Why Can’t I Add a Watermark in Word? Common Fixes That WorkIf you can’t add a watermark in Word, the most common reason is that you’re using Word for…
- Can You Merge Cells in OneNote? Steps and LimitsYes. In the OneNote desktop app for Windows, you can merge adjacent cells in a table: select the…
- How to Enable Track Changes in Microsoft Word DocumentsTo enable Track Changes in Word, open the document, select the Review tab, and switch on Track Changes.…
Sources: Function behaviour and menu paths: Microsoft Support documentation for Excel. Method & sources
Spotted an error in this guide? Let us know.