Data Structures in R Interview Questions for R Programming
25 Data Structures in R questions with answers for r programming roles — 7 easy, 14 medium, 4 hard.
About Data Structures in R
R work revolves around vectors, lists, matrices, data frames and tibbles. This topic covers subsetting with [ ], [[ ]] and $, the apply family, strings, dates, data.table and list-columns. Interviewers test whether you can choose the right structure, index it correctly and combine many files or pieces efficiently without slow loops.
Sheet progressStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
✓ 3 questions free • Unlock the rest in seconds
01
What is the difference between a vector and a list in R?
An atomic vector holds elements of a single type, such as all numbers or all strings, while a list can hold elements of any type, including other lists, data frames or functions. c(1, 'a') coerces to character, but list(1, 'a', TRUE) keeps each type. Lists are used for nested data such as JSON responses and for returning multiple results from a function, which is why model objects like lm() output are lists.
A data frame is a list of equal-length vectors, where each vector is a column with its own type. It is R's main structure for tabular data, similar to a spreadsheet or SQL table. str(df) shows column types, nrow() and ncol() give dimensions and summary() gives quick statistics. Tibbles from the tidyverse are modern data frames that print neatly, never convert strings to factors and do not partially match column names.
A matrix is a two-dimensional atomic vector, so all elements share one type, usually numeric. A data frame allows a different type per column. Matrices are faster for linear algebra, such as %*% multiplication, solve() and distance calculations, while data frames suit mixed real-world data. For example, the output of cor() is a matrix, while customer records with names, dates and amounts belong in a data frame. as.matrix() and as.data.frame() convert between them.
04
Show different ways to index vectors and data frames in R.
R indexes from 1 and supports positive, negative, logical and name-based indexing.
x <- c(a = 10, b = 20, c = 30, d = 40)
x[2] # 20
x[-1] # drop first
x[c('a', 'd')] # by name
x[x > 15] # logical filter
which(x > 15) # positions
df[df$age > 30, c('name', 'city')]
df[order(-df$salary), ][1:5, ] # top 5 salaries
05
Dates in your file look like 25/12/2025 and as.Date() returns NA. What is wrong and how do you fix it?
Indian files often store dates as dd/mm/yyyy, but as.Date() expects yyyy-mm-dd by default, so values become NA. I specify the format, as.Date(x, format = '%d/%m/%Y'), or use lubridate::dmy(x), which handles different separators automatically. Then I count NAs before and after conversion to confirm nothing failed silently. If the column came from Excel as serial numbers, I use as.Date(x, origin = '1899-12-30') instead.
An array is a multi-dimensional generalization of a matrix, created with array(data, dim = c(rows, cols, layers)). All elements share one type. For example, array(1:24, dim = c(2, 3, 4)) has four layers of 2 by 3 matrices, and you index with arr[1, 2, 3]. Arrays are used for image data, simulation outputs and time by region by product cubes, though for business analysis long-format data frames are usually easier to work with.
07
How do you explain technical results to non-technical managers?
I start with the business question and the answer in one sentence, then show one or two clear charts instead of tables of coefficients. For example, in a college project on customer churn, I said that customers with more than three complaints were twice as likely to leave, showed a simple bar chart and suggested a follow-up call process. I keep technical details in an appendix and invite questions so managers can decide confidently.
08
What is the difference between [ ], [[ ]] and $ when subsetting?
For lists, [ ] returns a sub-list, while [[ ]] and $ return the element itself. So lst['a'] is a list of length one and lst[['a']] is the value. $ allows partial name matching and cannot take a variable, while [[ ]] accepts a string variable like lst[[col]]. On data frames, df['x'] returns a one-column data frame, and df[['x']] or df$x returns a vector. Think of [ ] as the train car and [[ ]] as its contents.
When you subset a single column or row from a matrix or base data frame with [ ], R simplifies the result to a vector by default. Writing m[, 1, drop = FALSE] keeps it as a matrix or data frame. This matters inside functions, because code expecting a data frame breaks when a selection leaves only one column. Tibbles never drop dimensions, which is one reason developers prefer them in reusable code and packages.
apply() works over rows or columns of a matrix, lapply() applies a function to each element of a list and returns a list, sapply() simplifies the result to a vector or matrix when possible, vapply() is like sapply() but requires a declared output type, making it safer, and mapply() iterates over several vectors in parallel. tapply() applies a function by groups. For example, sapply(df, class) returns the class of each column.
I list the files with list.files(pattern = 'csv$', full.names = TRUE), then read them all at once with readr::read_csv(files, id = 'file'), which also records the source file. Alternatively I use purrr::map() with read_csv and dplyr::bind_rows(). Before combining, I check that column names and types match, because one file with text in a numeric column will fail or coerce the whole column. I then derive the month from the file name for traceability.
13
A loop that adds rows to a data frame with rbind() takes very long. How do you speed it up?
Calling rbind() inside a loop copies the growing data frame each iteration, so time grows roughly quadratically. I instead store each piece in a preallocated list, results[[i]] <- piece, and combine once at the end with dplyr::bind_rows() or data.table::rbindlist(), which is the fastest. Better still is to vectorize the computation or use purrr::map() followed by list_rbind(). On 10,000 iterations this can cut runtime from minutes to seconds.
14
What is a tibble and how does it differ from a base data frame?
A tibble is the tidyverse version of a data frame. It prints only the rows and columns that fit the screen along with column types, never converts strings to factors, never changes column names, does not partially match with $ and always returns a tibble when subsetting with [ ]. It also supports list-columns easily. You convert with as_tibble(). Tibbles prevent many silent bugs, though some older packages expect base data frames.
data.table is a high-performance package for large tabular data. Its syntax DT[i, j, by] means filter rows with i, compute j, grouped by by. It updates columns by reference with :=, avoiding copies, and offers fast keyed joins and fread()/fwrite() for file IO. For example, DT[city == 'Delhi', .(avg_sal = mean(salary)), by = dept] filters and aggregates in one step. It is popular for datasets with tens of millions of rows.
16
Write common data.table operations for filtering, aggregating and joining.
Base R stores dates as the Date class, counting days since 1970-01-01, and date-times as POSIXct, counting seconds. as.Date('2026-03-15') parses ISO strings and format() controls output. The lubridate package simplifies parsing with ymd(), dmy() and mdy(), extracting parts with month() and wday(), and arithmetic like date + months(1). Time zones matter: Indian data usually uses 'Asia/Kolkata', and mixing UTC with IST can shift records across days.
19
After merging two data frames you get more rows than expected. What happened?
Extra rows after a join usually mean the key is duplicated in one or both tables, so each match multiplies rows. I check uniqueness with df %>% count(key) %>% filter(n > 1) on both sides. Then I decide whether to deduplicate, aggregate before joining or join on a composite key such as customer_id plus month. In dplyr 1.1 and later, the relationship argument, for example 'many-to-one', makes the join fail loudly when this assumption breaks.
20
Describe a time you found a data quality issue in your analysis.
Situation: while preparing a monthly revenue dashboard, totals were 8 percent higher than finance figures. Task: find the cause before the review meeting. Action: I traced row counts after each step in my R script and found a join on customer ID that duplicated rows because some customers had two active addresses. I deduplicated the address table and added a row-count check. Result: numbers matched finance, and the check now runs in every refresh.
21
Tell me about a time you had two urgent analysis requests at the same time.
Situation: two managers needed different analyses on the same Friday. Task: deliver both without compromising quality. Action: I asked each what decision the analysis would support and the minimum needed by Friday, reused one cleaned dataset in R for both, and shared a draft of the simpler one on Wednesday for early feedback. Result: both received usable outputs on time, and the fuller version of the second analysis followed on Monday as agreed.
A list-column is a data frame column whose cells are lists, such as nested data frames or fitted models. With tidyr::nest() you group data, for example by region, into a column of sub-data frames, then use purrr::map() to fit a model per region and broom::tidy() to extract coefficients. This keeps data, models and results aligned row by row, which is cleaner than managing separate lists of models and names.
23
Write code to fit one regression model per group using nested data.
Not by much. R keeps a global string pool, so each unique string is stored once and a character vector only holds pointers, which makes repeated values already compact. Factors still matter for controlling level order in plots and models and for representing a fixed set of categories. For huge data, data.table and arrow handle strings efficiently, and converting high-cardinality IDs to factors usually adds overhead without any benefit.
25
An API returns deeply nested JSON. How do you turn it into a tidy data frame in R?
I make the request with httr2, handling authentication and pagination, then parse with jsonlite::fromJSON(), which simplifies arrays of objects into data frames, using flatten = TRUE to spread nested objects into columns. For deeper nesting I keep a list and use tidyr::unnest_wider() and unnest_longer() to expand list-columns step by step. Optional keys become NA, so I check missing fields across records and validate types before analysis.
Frequently asked questions
How important is Data Structures in R in R Programming interviews?
R work revolves around vectors, lists, matrices, data frames and tibbles. This topic covers subsetting with [ ], [[ ]] and $, the apply family, strings, dates, data.table and list-columns. Interviewers test whether you can choose the right structure, index it correctly and combine many files or pieces efficiently without slow loops.
How should I use the Data Structures in R sheet?
Go top to bottom — easy to hard. Answer before opening each answer, tick what you solved and save misses to Last-Minute Revision.