142 R Programming Language Interview Questions and Answers (2026)

R is no longer a niche tool for statisticians — it runs production analytics, reporting pipelines, and modeling work at companies that hire seriously. Interviewers now expect real fluency: how vectorisation actually works, how scoping and environments behave, why coercion bites you. Walk in shaky on those and it shows fast.
This guide gives you 142 questions with concise, interview-ready answers and code where it helps. It's worked from Junior to Mid to Senior, so you build from data types and subsetting up to tidyverse, OOP, memory, and reproducible reporting. Work through it and you'll speak about R like someone who uses it daily.
Q1.What are some disadvantages of using R?
R is powerful for statistics but has real trade-offs: it can be memory-hungry, slower than compiled languages, and its permissive design invites inconsistent, error-prone code.
Memory-bound: R holds objects in RAM by default, so datasets larger than memory need extra packages (data.table, arrow, disk.frame) or a database.
Slower for loops: Being interpreted, tight scalar loops are slow; you must vectorise or drop into C/C++ via Rcpp.
Inconsistent ecosystem: Multiple paradigms and object systems (S3, S4, R5) plus base vs tidyverse styles create a steep, fragmented learning curve.
Uneven package quality: CRAN is vast but community-driven; documentation and reliability vary widely.
Weaker for general software: Less suited to production web services, mobile, or large engineering systems than Python or Java.
Silent coercions: Loose typing and automatic coercion can hide bugs instead of raising errors.
Q2.What is R programming, and what are its key features that make it suitable for statistical computing and data analysis?
R is an open-source language and environment built specifically for statistical computing, data analysis, and visualisation, designed by statisticians so that data structures and modelling functions feel native rather than bolted on.
Built for statistics: Rich built-in models and distributions: lm(), glm(), t.test(), and full probability families out of the box.
Vectorised operations: Operations apply element-wise across whole vectors, so analysis code is concise and fast without explicit loops.
Native data structures: The data.frame (and factors for categoricals) models tabular data directly, mirroring how statisticians think.
Visualisation: Strong plotting via base graphics and ggplot2 for publication-quality graphics.
Package ecosystem: CRAN and Bioconductor provide thousands of domain-specific statistical and data tools.
Reproducibility: R Markdown and Quarto weave code, output, and prose into reproducible reports.
Q3.What is RStudio and how does it help in R programming?
RStudio is the dominant integrated development environment (IDE) for R, providing an editor, console, and workspace tools in one interface that make writing, running, and debugging R code far more productive than the bare console.
Four-pane layout: Source editor, interactive console, environment/history, and files/plots/packages/help in a single view.
Productivity features: Syntax highlighting, autocompletion, inline help, and run-selection let you develop iteratively.
Environment inspection: View live objects, data frames, and variable values without printing them manually.
Integrated tooling: Built-in debugger, Git integration, package building, and project management via .Rproj files.
Reproducible authoring: First-class support for R Markdown, Quarto, and Shiny app development.
Note: RStudio is an IDE, not R itself: it wraps and calls the R engine installed separately.
Q4.What is the difference between R and other programming languages?
The core difference is purpose and design: R was created by statisticians as a domain-specific language where vectors, data frames, and statistical models are first-class citizens, unlike general-purpose languages that treat data analysis as an add-on.
Statistics-first design: Modelling, distributions, and vectorised math are native, not library afterthoughts.
Vector-based: The atomic unit is a vector, not a scalar: even 1 is a length-one vector, so operations broadcast automatically.
1-based indexing: R indexes from 1, unlike the 0-based indexing of C, Java, and Python.
Functional leanings: Functions are first-class objects and much work is done with apply-family and functional patterns rather than loops.
Dynamic and interactive: REPL-driven, dynamically typed, and geared to exploratory analysis rather than large compiled systems.
Assignment convention: Idiomatic use of <- for assignment is distinctive to R.
Q5.What is the .RData workspace file and what are the pros and cons of saving/restoring it?
.RData workspace file and what are the pros and cons of saving/restoring it?.RData is a binary file that stores your entire R workspace (all objects in the global environment) so you can restore a session exactly where you left off.
What it is:
Saved with save.image() or automatically on exit; loaded with load() or at R startup.
RStudio prompts to "Save workspace image?" on quit, writing to .RData in the working directory.
Pros:
Convenience: recover large or slow-to-compute objects without rerunning code.
Preserves interactive state across sessions.
Cons:
Hurts reproducibility: results depend on hidden state, not on a runnable script.
Stale objects can silently mask bugs (old variable still in memory).
Can be large and machine-specific.
Best practice: Disable auto-restore and script everything; use saveRDS() for specific objects you actually want to persist.
Q6.Explain the basic data structures in R, including vectors, lists, matrices, and data frames, and their typical use cases.
R's core structures differ along two axes: dimensionality (1D, 2D) and whether elements must share one type (homogeneous) or can be mixed (heterogeneous).
Vector (1D, homogeneous):
The atomic building block; all elements share one type (numeric, character, logical).
Use for a single column of measurements or a sequence.
List (1D, heterogeneous):
Each element can be any type or structure, including other lists.
Use for grouping unlike objects: model outputs, JSON-like data.
Matrix (2D, homogeneous):
A vector with a dim attribute of rows and columns; all one type.
Use for numeric/linear-algebra computation.
Data frame (2D, heterogeneous):
A list of equal-length columns where each column can be a different type.
The standard structure for tabular datasets.
Q7.What is the fundamental difference between a vector and a list in R?
A vector is homogeneous (all elements share one atomic type), whereas a list is heterogeneous (each element can be any type or structure, including other lists).
Type constraint:
Vectors coerce mixed inputs to a single type (e.g. c(1, "a") becomes all character).
Lists keep each element as-is, no coercion.
Indexing: [ ] returns a sub-vector/sub-list; [[ ]] extracts a single element's contents (crucial for lists).
Use cases:
Vector: uniform data like a column of values.
List: nested or mixed data; the basis for data frames and model objects.
Q8.What are vectors in R?
Vectors are R's fundamental data structure: a one-dimensional, ordered collection of elements that all share the same atomic type. Even a single value in R is a length-1 vector.
Atomic types: logical, integer, double, character, plus complex and raw.
Creation and coercion: Built with c(); mixing types coerces to the most flexible type.
Vectorization: Operations apply element-wise (x + y), and shorter vectors recycle: this is idiomatic, fast R.
Q9.Can you explain the difference between a list and a data frame in R?
A data frame is a special kind of list: a list whose elements are all vectors of the same length, presented as a table. So every data frame is a list, but not every list is a data frame.
List (general): Elements can be any type and any length: mix a scalar, a vector, and a model object freely.
Data frame (constrained list):
All columns (list elements) must have equal length, giving a rectangular shape.
Has row.names and a class of data.frame, enabling 2D indexing df[i, j].
Practical takeaway: Use a plain list for ragged/heterogeneous collections; a data frame for tabular data.
Q10.Explain the concept of data frames in R.
A data frame is R's primary structure for tabular data: a list of equal-length columns where each column can hold a different type, so rows represent observations and columns represent variables.
Structure:
Internally a list; each column is one vector, all sharing the same length.
Columns are typed independently: numeric, factor, character, logical.
Access: df$col or df[["col"]] for a column; df[rows, cols] for subsetting.
Ecosystem:
Foundation for modeling, read.csv() output, and dplyr/tibble workflows.
Note: modern code often uses stringsAsFactors = FALSE (now the default in R 4.0+).
Q11.What is the difference between a matrix and a multi-dimensional array in R?
Both are atomic vectors with a dim attribute; a matrix is just the special 2-dimensional case of an array.
A matrix has exactly two dimensions: Created with matrix(); rows and columns only.
An array can have any number of dimensions:
Created with array() and a dim vector of length 2, 3, or more.
A 2-D array is identical to a matrix; class() returns both "matrix" and "array".
Shared constraint: All elements must be the same atomic type; mixed types force coercion (unlike a data.frame).
Q12.What are the different data types in R?
R has six atomic (vector) types plus higher-level structures built on top of them; most everyday code works with vectors, lists, and data frames.
Atomic types (all elements same type):
logical: TRUE/FALSE.
integer: whole numbers written with L (5L).
double (numeric): real numbers, the default for numbers.
character: strings.
complex and raw: rarely used (complex numbers, raw bytes).
Compound structures:
list: can hold mixed types and nested objects.
data.frame: a list of equal-length columns (tabular data).
factor: categorical data stored as integers with labels.
Q13.What are valid variable names in R?
A valid R name is made of letters, digits, dots, and underscores, and must start with a letter or a dot (not followed by a digit); anything else must be quoted with backticks.
Rules:
Allowed characters: letters, digits, ., and _.
Must begin with a letter or a dot; a leading dot cannot be followed by a digit (.2x is invalid).
Cannot start with a digit or underscore.
Names starting with a dot (.hidden) are hidden from ls().
Reserved words: Cannot use if, else, TRUE, function, etc.
Case sensitivity: x and X are different names.
Backtick escape: Non-syntactic names work if quoted: `my var` <- 1.
Q14.How do you convert data types in R?
Use the as.*() family of coercion functions to explicitly convert an object from one type to another.
Common converters:
as.numeric() / as.double(), as.integer(), as.character(), as.logical().
Structure converters: as.factor(), as.data.frame(), as.matrix().
Watch for failed conversions: Invalid conversions produce NA with a warning: as.numeric("abc") -> NA.
Factor trap: Converting a factor with as.numeric() returns the internal codes, not the labels; use as.numeric(as.character(f)).
Q15.How do you determine the data type of an object in R?
R offers several inspection functions; the key ones are class(), typeof(), and is.*() tests, which report the type at different levels.
class(): The high-level (S3/S4) class used for method dispatch, e.g. "data.frame", "factor".
typeof(): The internal storage type, e.g. "double", "integer", "list", "closure".
mode() and storage.mode(): Older, coarser descriptions of type; less used than the two above.
Predicate tests: is.numeric(), is.character(), is.data.frame() return TRUE/FALSE.
Overview: str() gives a compact summary of an object's structure and types, ideal for exploring.
Q16.What is the difference between an integer and a double in R, and what does the L suffix do?
L suffix do?Both are numeric, but an integer stores whole numbers exactly while a double stores double-precision floating-point values; the L suffix forces a literal to be an integer instead of the default double.
Default is double: Typing 5 creates a double; typeof(5) is "double".
The L suffix: 5L creates an integer; typeof(5L) is "integer".
Why it matters:
Integers use less memory and avoid floating-point rounding.
Mixed arithmetic promotes integers to doubles automatically.
Both report class() as "numeric"; use typeof() to see the real storage type.
Q17.What is the difference between print() and cat() in R?
print() and cat() in R?print() is a formatted display function that shows an object's structure with indices and quotes, while cat() concatenates and writes raw output for clean, human-readable text.
print():
Generic and object-aware: dispatches on class to format vectors, data frames, etc.
Shows quotes around strings and index markers like [1]; adds a newline; returns the object invisibly.
cat():
Concatenates arguments separated by sep and prints plainly (no quotes, no indices).
You control newlines with \n; returns NULL, so it's for side-effect output only.
When to use: Use print() for inspecting objects; use cat() for messages and building custom text output.
Q18.What is a factor in R, and why is it used for categorical variables?
A factor is R's data type for categorical data: it stores values as an integer vector mapped to a set of labelled levels, giving efficient storage and correct statistical handling of categories.
How it is stored: Internally an integer code per observation plus a levels attribute holding the distinct labels.
Why use it for categories:
Constrains values to a fixed, known set, so typos or invalid categories surface as NA.
Models like lm() treat factors correctly as categorical predictors (dummy coding) rather than as numbers.
Ordered factors capture rank (e.g. low < medium < high) for ordinal data.
Common gotcha: Converting a factor of numbers with as.numeric() gives the codes, not the labels; use as.numeric(as.character(x)).
Q19.Which data structure is used to store categorical variables in R?
The factor is R's dedicated structure for categorical variables, storing categories as integer codes tied to a set of character labels called levels.
Created with: factor(), optionally specifying levels and labels.
Two kinds:
Nominal (unordered) for plain categories.
Ordinal via ordered = TRUE when categories have a natural rank.
Why not a character vector: Factors enforce a valid set of categories and are handled correctly by modeling and plotting functions.
Q20.Explain the concept of factor levels in R.
Factor levels are the complete, ordered set of distinct categories a factor is allowed to take; each observation stores an integer that indexes into this level set.
What they define:
The allowed values: any data not matching a level becomes NA.
Their order, which controls sorting, plotting order, and the reference (baseline) category in models.
Default vs explicit: By default levels are the sorted unique values; pass levels = to set order or include categories not yet observed.
Managing them: levels() reads or renames them; droplevels() removes unused ones; relevel() changes the baseline.
Key point: Levels persist even if no data uses them, which matters for consistent grouping and tabulation.
Q21.Can you explain how to use the subset() function in R?
subset() function in R?subset() is a convenience function for filtering rows and selecting columns of a data frame using unquoted (non-standard-evaluation) column names, which makes interactive code shorter and more readable.
Arguments:
subset =: a logical expression selecting rows.
select =: columns to keep (bare names, ranges, or -name to drop).
Handy behaviors:
Column names are evaluated inside the data frame, so no df$ prefix needed.
Rows where the condition is NA are dropped (unlike raw [ indexing, which keeps NA rows).
Important caveat: Its NSE makes it risky inside functions/packages; use standard [ indexing or dplyr::filter() in programmatic code.
Q22.How do you create and subset a data frame in R?
You build a data frame with data.frame() (columns of equal length) and subset it with the two-index df[rows, cols] bracket syntax, or with $ and [[ for single columns.
Creating: data.frame(name = ..., age = ...); since R 4.0.0 strings stay character by default.
Two-dimensional subsetting:
df[rows, cols]: leave a slot empty to keep all (df[1:3, ]).
Rows via logical/positional index, columns via name or position.
Single-column access: df$age or df[["age"]] return a vector; df["age"] returns a one-column data frame.
Watch the drop trap: Selecting one column with df[, 1] silently returns a vector; use df[, 1, drop = FALSE] to keep it a data frame.
Q23.How do positive, negative, logical, and name-based indexing work in R?
R's [ operator supports four ways to select elements: positive integers keep, negative integers drop, logicals filter by mask, and character names match by label.
Positive indexing: x[c(1,3)] returns those positions; R is 1-based, and indices may repeat (x[c(1,1)]).
Negative indexing: x[-1] drops elements; you cannot mix positive and negative in one call.
Logical indexing: x[x > 5]: keep where TRUE; the mask is recycled to length, and NA in the mask yields NA elements.
Name-based indexing: x["a"] matches by name; unmatched names return NA.
Note: All four work on vectors and, in each dimension, on df[rows, cols].
Q24.What is the difference between the single bracket [, double bracket [[, and $ operators for subsetting in R?
[, double bracket [[, and $ operators for subsetting in R?They differ in what they return: [ preserves the container and can select many elements, while [[ and $ extract a single element out of it.
Single bracket [:
Returns an object of the same type as the original (a list stays a list, a vector stays a vector).
Can select multiple elements and supports negative indices, logicals, and names.
On a list, mylist[1] gives a length-1 list, not the element inside.
Double bracket [[:
Extracts one element and drops the containing structure: mylist[[1]] returns the element itself.
Takes a single index or name; can recurse with l[[c(1,2)]].
Dollar $:
Shorthand for [[ by name on lists and data frames: df$col.
Does partial matching and does not accept a variable holding a name (use [[ for programmatic access).
Q25.Explain how to create a function in R.
You create a function with the function keyword, assign it to a name, and it returns the value of its last evaluated expression (or an explicit return()).
Basic syntax: name <- function(args) { body }: arguments can have defaults like function(x, n = 1).
Return value: The last expression is returned implicitly; return() is only needed for early exit.
Components: Every function has formals() (arguments), body(), and environment().
Anonymous functions: You can define one inline without naming it, and R 4.1+ has \(x) x + 1 shorthand.
Q26.What is an anonymous function in R and what does the \(x) lambda shorthand mean?
\(x) lambda shorthand mean?An anonymous function is a function defined without binding it to a name, typically used inline where a function is expected (e.g. as an argument to lapply() or Map()). Since R 4.1, \(x) is a concise shorthand for function(x).
Definition:
A function object with formals and a body but no name, e.g. function(x) x^2.
Useful for short, one-off logic passed to higher-order functions.
The \(x) lambda shorthand:
Introduced in R 4.1; \(x) x^2 is identical to function(x) x^2.
The backslash echoes the lambda symbol; it just saves typing and reads well inline.
Caveat: It is pure syntactic sugar: same semantics, scoping, and lazy evaluation as any function.
Q27.What is the difference between the assignment operators <-, =, and <<-?
<-, =, and <<-?All three assign, but they differ in scope and idiom: <- is the standard assignment in the current environment, = also assigns but is mainly used for function arguments, and <<- assigns into an enclosing (parent) scope.
<- (preferred):
Idiomatic assignment in the current environment; works anywhere.
Style convention: reserve <- for real assignment for clarity.
=:
Assigns like <- at top level, but inside a call it binds a named argument, not a variable.
e.g. mean(x = 1:5) sets the argument, it does not create x.
<<- (super-assignment):
Searches enclosing environments for an existing binding and modifies it; if none is found it assigns in the global environment.
Used for closures/mutable state; use sparingly as it creates side effects.
Q28.Explain the scope of variables in R, including local and global variables.
Variable scope in R determines where a name is visible. Variables created inside a function are local to that function's environment and vanish when it returns; variables in the global environment (the workspace) are accessible from anywhere unless shadowed by a local name.
Local variables:
Created by assignment inside a function; live in that call's environment only.
Shadow global variables of the same name for the duration of the call.
Global variables:
Live in the global environment (.GlobalEnv); functions can read them via lexical scoping.
A plain <- inside a function never overwrites a global; use <<- for that.
Key rules:
Read access looks outward (local, then enclosing, then global); write access defaults to local.
Prefer passing values as arguments and returning results over relying on globals.
Q29.Can you explain the control flow statements in R?
R's control flow statements decide which code runs and how often: conditionals branch, loops repeat, and jump statements alter loop execution. They are ordinary language keywords, but note that R also favours vectorised operations over explicit loops.
Conditionals:
if / else branches on a single TRUE/FALSE value.
switch() selects a branch by matching a string or integer.
Loops:
for (x in seq) iterates over the elements of a vector or list.
while (cond) repeats as long as a condition holds.
repeat loops forever until you exit explicitly.
Jump statements: break exits the innermost loop; next skips to the next iteration.
R idiom:
if returns a value, so y <- if (a) 1 else 2 works.
Prefer vectorised functions and the apply family over explicit loops for performance and clarity.
Q30.How does the switch() statement work in R and when would you use it?
switch() statement work in R and when would you use it?switch() chooses one of several expressions based on the value of a selector, acting as a cleaner alternative to a long chain of if/else if when dispatching on a string or integer.
String matching:
switch(x, a = ..., b = ...) evaluates and returns the branch whose name equals x.
An unnamed final argument acts as the default when no name matches.
Fall-through: An empty case falls through to the next non-empty one, letting several inputs share code.
Integer matching: If the selector is numeric, it picks the branch by position (no default supported).
When to use it:
Dispatching on a mode/type string, choosing a method by name, or mapping codes to actions.
It is not vectorised: it evaluates one selector value at a time.
Q31.What is the difference between if/else and the vectorised ifelse() in R?
if/else and the vectorised ifelse() in R?if/else is a control-flow construct that branches once on a single scalar condition, whereas ifelse() is a vectorised function that tests every element of a vector and returns a vector of the same length.
if/else:
Expects a single TRUE/FALSE; a length>1 condition errors in R 4.2+ (previously warned).
Controls which block executes and returns that block's value.
ifelse(test, yes, no):
Evaluates elementwise and picks from yes or no per element, returning a vector shaped like test.
Both yes and no are fully evaluated, so it is not for lazy short-circuiting or side effects.
Gotchas:
ifelse() can strip attributes and mishandle NA in test (returns NA).
For clearer typed logic, dplyr::if_else() and case_when() are common alternatives.
Q32.What is the use of the which() function in R?
which() function in R?which() returns the integer positions (indices) where a logical vector is TRUE, letting you convert a condition into locations rather than a mask.
Core behaviour: Input a logical vector, output the indices of TRUE values; NA values are ignored.
Common helpers:
which.max() and which.min(): position of the largest/smallest element.
which(x, arr.ind = TRUE): returns row/column indices for matrices/arrays.
When to use it:
When you need the index itself, not just to subset (e.g. finding a row number).
Note: for plain subsetting, x[x > 5] is often cleaner than x[which(x > 5)].
Q33.What is the MARGIN argument in apply() and how does it control row versus column operations?
MARGIN argument in apply() and how does it control row versus column operations?MARGIN tells apply() which dimension to iterate over: 1 applies the function to each row, 2 to each column, and c(1, 2) to each individual element.
MARGIN = 1 (rows): The function receives each row as a vector, so apply(m, 1, sum) gives one result per row.
MARGIN = 2 (columns): The function receives each column as a vector: apply(m, 2, mean) gives a per-column mean.
Mnemonic: The margin is the dimension that is preserved in the output; 1 keeps rows, 2 keeps columns, matching the order in dim().
Caveat: for simple row/column sums and means, prefer rowSums(), colSums(), rowMeans(), colMeans(): they are far faster than apply().
Q34.What is the difference between & and && (and | and ||) in R?
& and && (and | and ||) in R?The single forms (&, |) are vectorized and operate element-by-element across whole vectors; the double forms (&&, ||) evaluate only a single logical value and short-circuit.
& and |:
Vectorized: c(T,F) & c(T,T) returns c(TRUE, FALSE).
Use them for filtering and subsetting, e.g. inside df[x > 0 & y < 5, ].
&& and ||:
Scalar and short-circuiting: && stops at the first FALSE, || at the first TRUE.
Use them in control flow like if conditions where you need one guaranteed scalar.
Interview trap: Since R 4.3, passing a vector of length > 1 to && or || is an error (previously a warning), so never use them on vectors.
Q35.What does the %in% operator do in R and when would you use it?
%in% operator do in R and when would you use it?%in% tests membership: for each element of the left operand it returns TRUE if that value appears anywhere in the right operand, producing a logical vector the same length as the left side.
What it does:
c(1, 5, 9) %in% c(1, 2, 3) returns c(TRUE, FALSE, FALSE).
It is a readable wrapper around match(x, table, nomatch = 0) > 0.
When to use it:
Filtering rows whose value is in a set: df[df$region %in% c("N","S"), ].
Cleaner than chaining multiple == with |.
Caveat: It never returns NA; an NA on the left is FALSE unless NA is in the table. Use %in% for membership, not equality testing.
Q36.How do seq(), rep(), seq_along(), and seq_len() differ, and why prefer seq_along in loops?
seq(), rep(), seq_along(), and seq_len() differ, and why prefer seq_along in loops?All generate sequences, but they differ in flexibility and safety: seq() is the general-purpose generator, rep() repeats values, and seq_along() / seq_len() are fast, safe helpers for building index sequences.
seq(): Flexible: seq(1, 10, by = 2) or seq(0, 1, length.out = 5).
rep(): Repeats elements: rep(c(1,2), times = 3) or rep(c(1,2), each = 3).
seq_along(x): Returns 1:length(x) but safely; on an empty x it returns an empty sequence.
seq_len(n): Returns 1:n, and seq_len(0) correctly yields an empty sequence.
Why prefer seq_along in loops: The classic bug: 1:length(x) gives c(1, 0) when x is empty, so the loop runs twice instead of zero times. seq_along(x) avoids this.
Q37.How do you read and write data in R?
R has base functions and faster package alternatives for moving data in and out: text/CSV via read.csv() / write.csv(), R-native binary via saveRDS() / readRDS(), and specialized readers for other formats.
Delimited text:
read.csv(), read.table(), write.csv() in base R.
Faster: readr::read_csv() and data.table::fread() for large files.
R binary objects:
saveRDS() / readRDS() for a single object (preserves types, class, factors).
save() / load() for multiple named objects in one .RData file.
Other formats: readxl::read_excel() for Excel, jsonlite for JSON, and DBI + a driver for databases.
Tip: prefer saveRDS() over CSV when round-tripping R objects, since CSV loses type and structure information.
Q38.What is the purpose of the str() function versus the summary() function in R?
str() function versus the summary() function in R?str() shows the structure of an object (its type, dimensions, and a preview of contents), while summary() gives a statistical or content summary. In short: str() answers "what is this object?" and summary() answers "what's in the data?".
str():
Compactly displays type, length/dimensions, column classes, and first few values.
Ideal first look at any object, especially nested lists and data frames.
summary():
Generic function: for a numeric column it gives min, quartiles, median, mean, max; for factors it gives counts.
Dispatches on class, so summary() on a fitted model (e.g. lm) prints coefficients and fit statistics.
Rule of thumb: use str() to inspect structure/types, summary() to inspect distributions or model output.
Q39.How do you check the structure of a data frame in R?
Use str() for a compact overview of a data frame's structure: it shows dimensions, each column's type, and sample values in one view.
str() is the primary tool: Prints number of observations and variables, then each column's class (num, chr, factor) with the first few values.
Complementary functions:
dim(), nrow(), ncol() for size; names() or colnames() for column names.
head() and tail() to preview rows; summary() for per-column distribution stats.
glimpse() from dplyr is a tidyverse alternative that fits more columns horizontally.
class() confirms the object is a data.frame (or tibble), which affects how it prints and behaves.
Q40.How do you plot data in R?
R has two main plotting systems: base graphics (plot() and friends) for quick exploration, and ggplot2 for a layered, publication-quality grammar of graphics.
Base graphics:
plot(x, y) scatter/line, hist(), boxplot(), barplot(); fast and dependency-free.
Builds a plot by drawing then adding (lines(), points(), legend()) onto an existing canvas.
ggplot2 (grammar of graphics):
Map data to aesthetics with aes(), then add layers (geoms) with +.
Handles faceting, scales, and themes cleanly; preferred for complex or grouped visualizations.
Rule of thumb: base for a quick look, ggplot2 for anything layered, grouped, or presented.
Q41.Explain the purpose of the dplyr package and its key verbs.
dplyr package and its key verbs.dplyr provides a small, consistent set of "verbs" for data manipulation: each takes a data frame, does one clear transformation, and returns a data frame, so they chain naturally with the pipe.
Row and column verbs:
filter(): keep rows matching conditions.
select(): pick or drop columns.
arrange(): reorder rows by column values.
mutate(): create or modify columns.
Aggregation:
summarise(): collapse rows into summary statistics.
group_by(): split data into groups so verbs operate per group (commonly paired with summarise()).
Joins: left_join(), inner_join(), etc. combine tables by key.
It works on data frames, tibbles, and databases (via dbplyr) using the same syntax.
Q42.How do you handle missing values in R using na.rm, is.na, and complete.cases?
na.rm, is.na, and complete.cases?R represents missing values as NA, and these three tools cover the common needs: na.rm ignores NAs in a calculation, is.na() detects them, and complete.cases() finds rows with no NAs.
na.rm = TRUE: An argument to aggregation functions (mean(), sum(), sd()) that drops NAs before computing; without it these return NA.
is.na(): Returns a logical vector marking NA positions; use it to count (sum(is.na(x))), filter, or replace missing values. Never test with x == NA (always NA).
complete.cases(): Returns TRUE for rows with no NAs across selected columns; handy for listwise deletion (df[complete.cases(df), ], similar to na.omit()).
Q43.What does the table() function do and how is it used for cross-tabulation?
table() function do and how is it used for cross-tabulation?table() counts the frequency of unique values in one or more factors/vectors, producing a contingency table: one variable gives counts, two or more give a cross-tabulation.
One variable: frequency counts: table(x) returns how many times each level of x occurs.
Two variables: cross-tabulation: table(x, y) builds a matrix with rows for x and columns for y, counting each combination.
Handling NAs: By default NAs are dropped; use useNA = "ifany" to include them.
Derived helpers: prop.table() converts counts to proportions; margin.table() or addmargins() add row/column totals; xtabs() does the same via a formula.
Q44.Can you explain the process and key functions for installing and loading R packages, and discuss best practices for package management?
You install a package once from a repository with install.packages() and then load it into each session with library(); good management centers on reproducibility: pinning versions and isolating each project's dependencies.
Install vs load:
install.packages("dplyr") downloads from CRAN into your library (once per version).
library(dplyr) attaches it for use; do this every session, and it errors if missing.
requireNamespace() or pkg::fun() use a package without attaching it (good inside packages/scripts).
Sources beyond CRAN: devtools::install_github() or remotes for development versions; Bioconductor via BiocManager.
Best practices:
Use renv to snapshot exact versions per project into a lockfile for reproducibility.
Prefer pkg::fun() in scripts/packages to avoid namespace collisions and make dependencies explicit.
Load packages at the top of scripts; avoid install.packages() calls inside code that others run.
Q45.What is an R package, and what is its purpose?
An R package is a structured, shareable bundle of R functions, data, documentation, and metadata that extends R's capabilities and makes code reusable and distributable.
Purpose:
Package related functionality together so it can be installed, versioned, and reused across projects.
Ship documentation and examples alongside code so users know how to use it.
What it contains: R code (in R/), help files (man/), metadata (DESCRIPTION, NAMESPACE), and optionally data and vignettes.
Distribution: shared via repositories like CRAN or Bioconductor, or directly from GitHub.
Q46.What is CRAN and how do you install packages from it?
CRAN (the Comprehensive R Archive Network) is R's official, curated repository of packages and R distributions; you install from it with install.packages().
What CRAN is:
A mirrored network hosting thousands of vetted packages that must pass R CMD check on multiple platforms.
The default source when you call install.packages().
Installing:
Install once with install.packages("pkg"), then load per session with library(pkg).
Keep current with update.packages().
Q47.Can you describe the process of creating a scatter plot using ggplot2?
ggplot2?A scatter plot in ggplot2 is built by initializing a plot with your data and aesthetic mapping, then adding a geom_point() layer, and optionally scales, labels, and a theme.
Start with ggplot(): Pass the data frame and set aes(x = ..., y = ...) to map the two continuous variables.
Add points with geom_point(): Add color or size inside aes() to encode extra variables.
Refine (optional): Add trend with geom_smooth(), adjust axes with scales, label with labs(), and style with a theme.
Q48.What is R Markdown, and what are its use cases for literate programming and reproducible reporting?
R Markdown is a document format that weaves narrative text, R code, and its output into a single reproducible file that can render to HTML, PDF, Word, slides, or dashboards.
How it works:
knitr executes code chunks and captures results; pandoc converts the merged Markdown to the target format.
A YAML header controls output type and options.
Literate programming: Prose and code live together, so the reasoning and the computation are documented as one narrative.
Reproducible reporting use cases:
Analyses that regenerate figures, tables, and numbers from source data on every render, eliminating copy-paste errors.
Parameterized reports (via params) for recurring outputs, plus notebooks, dashboards (flexdashboard), and even books/websites.
Q49.How does R compare to Python for data science applications from a programming language perspective?
Both are top data-science languages, but R is a specialist built by statisticians while Python is a general-purpose language that grew data tools: R often wins for statistics and visualisation, Python for engineering, production, and ML pipelines.
Design origin: R is domain-specific for stats; Python is general-purpose, so it integrates more naturally into apps, APIs, and deployment.
Statistical depth: R ships advanced statistical methods and cutting-edge academic packages first; Python relies on statsmodels and scipy.
Visualisation: ggplot2 is a benchmark for statistical graphics; Python's matplotlib/seaborn are capable but more verbose.
Machine learning and scale: Python dominates deep learning and MLOps (scikit-learn, PyTorch, TensorFlow).
Syntax and paradigm: R is more functional and vectorised; Python reads more like general programming and enforces cleaner structure.
Interoperability: They coexist: reticulate runs Python from R, so the choice is rarely all-or-nothing.
Q50.What is R and why is it considered a vectorised, functional programming language?
R is a statistical programming language whose two defining traits are that operations act on whole vectors at once (vectorised) and that functions are first-class values you can pass, return, and compose (functional).
Vectorised:
Arithmetic and functions apply element-wise across a vector without explicit loops, e.g. x + y adds two vectors position by position.
This is faster and clearer because the looping happens in optimised C internally.
Recycling extends shorter vectors to match longer ones.
Functional:
Functions are objects: you can store them, pass them as arguments, and return them.
Higher-order tools like lapply(), sapply(), and Map() replace loops with function application.
Encourages pure, side-effect-free transformations of data.
Q51.What is the difference between running R with Rscript versus the interactive REPL?
Rscript versus the interactive REPL?Rscript runs an R script non-interactively from the command line (ideal for automation and batch jobs), while the REPL is the interactive console where you type expressions and see results immediately (ideal for exploration).
REPL (interactive):
Read-eval-print loop: each expression is auto-printed, keeping state in a live session for exploratory work.
Started by running R or working inside RStudio.
Rscript (batch):
Executes a whole .R file top to bottom then exits, with no auto-printing (use print() or cat() for output).
Suited to cron jobs, pipelines, and reproducible runs; accepts arguments via commandArgs().
Key behavioural differences:
REPL auto-prints results; Rscript does not.
Rscript starts a clean, non-interactive session; interactive() returns FALSE.
Q52.What is the working directory in R and how do options() and getOption() configure session behaviour?
options() and getOption() configure session behaviour?The working directory is the folder R treats as the default location for reading and writing files, while options() and getOption() set and retrieve global session settings that control R's behaviour like number formatting and warnings.
Working directory:
Query it with getwd() and change it with setwd().
Relative file paths resolve against it, so it affects read.csv(), write.csv(), etc.
Prefer project-relative paths (RStudio Projects, here::here()) over hard-coded setwd() for reproducibility.
options():
Sets global session parameters, e.g. options(digits = 4), options(stringsAsFactors = FALSE), or options(warn = 2).
Called with no arguments it returns the full list of current options.
getOption(): Retrieves a single option's value, e.g. getOption("digits"), with an optional default if unset.
Scope: These settings last only for the session; put them in .Rprofile to apply them at startup.
Q53.Explain the difference between a matrix and a data frame in R. When would you choose one over the other?
A matrix is a homogeneous 2D structure (every cell the same type), while a data frame is a heterogeneous table where each column can have its own type. Choose by whether your columns are all the same type.
Matrix:
Really a vector with a dim attribute; all elements one type (usually numeric).
Supports fast matrix algebra (%*%, solve()).
Data frame:
A list of columns of equal length; mixed types allowed per column.
Columns have names; each is accessible via $.
When to choose:
Matrix: numerical computation, images, distance matrices, model matrices.
Data frame: real-world datasets mixing numbers, factors, and strings.
Q54.How do attributes and the class() of an object work in R?
class() of an object work in R?Attributes are metadata attached to any R object (name-value pairs like names, dim, class); class() reads the special class attribute that tells R's method dispatch how to treat the object.
Attributes:
Get/set with attr(x, "name") or view all via attributes(x).
They transform behavior: adding a dim attribute turns a vector into a matrix.
class():
If no explicit class attribute is set, class() returns an implicit class based on type/structure (e.g. "numeric", "matrix").
Setting it drives S3 dispatch: print(x) calls print.myclass() if it exists.
Practical note: class() gives the OO class; typeof() gives the underlying storage type, and they can differ.
Q55.What is the difference between NULL, NA, NaN, and Inf in R, and how do you handle missing values?
NULL, NA, NaN, and Inf in R, and how do you handle missing values?They represent four distinct concepts: NULL is the absence of a value, NA is a missing value, NaN is an undefined numeric result, and Inf is infinity.
NULL: The empty object, length 0; used to drop elements or signal "nothing here". Test with is.null().
NA: A missing value of length 1, exists per type (NA_integer_, NA_character_). Test with is.na().
NaN: "Not a Number": undefined math like 0/0. It is also treated as NA by is.na(), but is.nan() is specific.
Inf: Positive or negative infinity, e.g. 1/0. Test with is.infinite().
Handling missing values:
Most functions propagate NA; use na.rm = TRUE (in mean(), sum()) or remove rows with na.omit().
Never compare with == NA (yields NA); always use is.na().
Q56.Describe the different atomic data types in R and R's implicit coercion rules.
An atomic vector holds elements of a single type, and when types are mixed R silently coerces them all to the most flexible common type.
The six atomic types: logical, integer, double, character, complex, raw.
Coercion hierarchy (least to most flexible):
logical -> integer -> double -> character.
Combining types promotes everything to the highest present type.
Logical shortcut: In arithmetic, TRUE becomes 1 and FALSE becomes 0, so sum(x > 5) counts matches.
Explicit vs implicit: Implicit coercion happens automatically; use as.*() functions to coerce deliberately.
Q57.How does implicit type coercion work in R?
Implicit coercion is R automatically converting values to a common type when operations or containers require homogeneity, always promoting toward the more flexible type so no information is lost.
The coercion hierarchy:
Least to most flexible: logical < integer < double < character.
R promotes all elements up to the highest type present.
In atomic vectors: A vector holds one type, so c(1, "a", TRUE) becomes all character.
In arithmetic and logic: Logicals coerce to numbers: TRUE becomes 1 and FALSE becomes 0, so sum(c(TRUE, FALSE, TRUE)) is 2.
Explicit override: Use as.numeric(), as.character(), etc., when you need to force a direction; invalid conversions produce NA with a warning.
Q58.Why can comparing floating-point numbers with == be problematic in R?
== be problematic in R?Because doubles are stored in finite binary floating point, many decimals cannot be represented exactly, so two values that are mathematically equal may differ by a tiny rounding error and fail an exact == test.
The root cause: Numbers like 0.1 and 0.3 have no exact binary form, so 0.1 + 0.2 == 0.3 returns FALSE.
Errors accumulate: Repeated arithmetic compounds rounding error, widening the gap from the true value.
The fix: compare with tolerance:
Use all.equal(), which allows a small tolerance (default ~1.5e-8), or test abs(a - b) < tol.
Wrap all.equal() in isTRUE() since it returns a message string, not FALSE, on mismatch.
Q59.What is the difference between == , identical(), and all.equal() in R?
== , identical(), and all.equal() in R?They differ in strictness and vectorization: == is an element-wise value test, identical() is a single exact all-or-nothing test, and all.equal() is a tolerant near-equality test for numerics.
==:
Vectorized and element-wise, returns a logical vector.
Applies coercion and is exact, so floating-point rounding can make it fail; NA propagates.
identical():
Returns a single TRUE/FALSE, never a vector.
Strict: checks type, length, attributes, so identical(1L, 1) is FALSE (integer vs double).
all.equal():
Tests near-equality within a tolerance, ideal for doubles.
Returns TRUE or a difference message (not FALSE), so wrap it in isTRUE() for a clean boolean.
Q60.What are factors in R and how do levels and ordered factors work?
A factor is R's data type for categorical data: it stores values as integer codes plus a set of levels (the distinct labels), which saves memory and signals to models that the variable is categorical rather than numeric or free text.
Structure:
Internally an integer vector with a levels attribute mapping each integer to a label.
Create with factor(x, levels = ...); any value not in levels becomes NA.
Levels control order and display:
By default levels are sorted alphabetically, which drives axis order, table order, and the reference level in models.
Set them explicitly to get a meaningful order (e.g. c("low","med","high")).
Ordered factors:
Made with factor(x, ordered = TRUE) or ordered(); levels carry a rank so comparisons like < and > are meaningful.
In models they get polynomial contrasts by default, unlike unordered factors.
Common trap: Converting a factor of numbers with as.numeric() returns the integer codes, not the labels; use as.numeric(as.character(f)).
Q61.What is the stringsAsFactors history and why did it matter?
stringsAsFactors history and why did it matter?Historically, functions like data.frame() and read.csv() defaulted stringsAsFactors = TRUE, silently turning every character column into a factor; this caused so many bugs that R 4.0.0 (2020) changed the default to FALSE.
Why it existed: In early R, memory was scarce and factors were cheaper than repeated strings, and most workflows fed data straight into models that need factors.
Why it caused pain:
Unexpected factors broke string operations, introduced surprise NAs for unseen levels, and made as.numeric() return codes instead of values.
Merging or rbind-ing data with mismatched levels produced silent errors.
The fix:
Since R 4.0.0 the default is stringsAsFactors = FALSE; strings stay strings unless you opt in.
Interview point: always set it explicitly in older/portable code so behavior does not depend on R version.
Q62.What is the forcats package used for and what problems with factors does it solve?
forcats package used for and what problems with factors does it solve?forcats is a tidyverse package that provides a consistent, verb-based toolkit for working with factors, especially reordering and relabeling levels, tasks that are clumsy with base R.
Reordering levels:
fct_reorder(): order levels by another variable (great for readable plots).
fct_infreq() and fct_rev(): order by frequency or reverse the order.
fct_relevel(): move specific levels (e.g. set a model reference level).
Relabeling and combining:
fct_recode(): rename levels; fct_collapse(): merge several into one.
fct_lump(): bucket rare levels into "Other".
Handling missing/new levels: fct_explicit_na() turns NA into a visible level; fct_expand()/fct_drop() add or remove levels.
Problem it solves: Base R level manipulation means fiddling with the levels attribute directly; forcats gives predictable, pipe-friendly functions with clear names.
Q63.How does the split() function work in R?
split() function work in R?split() divides a vector or data frame into a list of groups defined by a factor (or list of factors), producing one list element per level, which is the classic setup for a split-apply-combine workflow.
Signature:
split(x, f): x is the data, f is a grouping factor coerced from whatever you pass.
Returns a named list; names are the factor levels.
Typical use:
Pair with lapply()/sapply() to apply a function per group, then recombine.
Multiple factors create groups for every combination (interaction).
Details:
Empty factor levels still produce (empty) list elements unless drop = TRUE.
unsplit() reverses the operation.
Q64.What does the drop argument do when subsetting in R?
drop argument do when subsetting in R?drop controls whether subsetting collapses a result to a lower-dimensional object: when a matrix or data-frame selection leaves a single row or column, drop = TRUE (often the default) reduces it to a vector, while drop = FALSE preserves the original structure.
Defaults differ by object: Matrices and data frames default to drop = TRUE, so a one-column selection becomes a plain vector.
Why it bites you: Code that expects a data frame can break when a filter happens to return one column, causing downstream ncol() or column-name calls to fail.
Defensive practice:
Set drop = FALSE in functions to guarantee stable dimensions.
tibbles (dplyr) never drop dimensions, which avoids this class of bug.
Q65.What does it mean that functions are first-class objects in R?
It means functions in R are ordinary values: they can be stored in variables, passed as arguments, returned from other functions, and created at runtime, just like vectors or lists.
Assigned to names and stored: f <- function(x) x^2 just binds a function value to a name; you can also put functions in a list.
Passed as arguments: This powers the apply family and Map()/Reduce(), which take a function as input.
Returned from functions: Enables closures: a returned function captures the enclosing environment (a factory pattern).
Created and inspected at runtime: Anonymous functions and tools like body() and formals() treat code as data.
Q66.What is the ... (dots) argument in R and when would you use it?
... (dots) argument in R and when would you use it?The ... (dots) is a special argument that captures an arbitrary number of extra arguments so a function can pass them along or accept a variable-length set of inputs.
Forwarding arguments: Most common use: relay unknown arguments to an inner function, e.g. a wrapper passing ... to plot() or paste().
Variable-length inputs: Functions like c(), sum(), and paste() accept any number of values via dots.
Accessing the contents: Use list(...) to capture them as a list and ...length() / ..1 to inspect individually.
Trade-off: Flexible but hides the true interface, and misspelled argument names silently fall into ... instead of erroring.
Q67.How does R match function arguments by position, name, and partial matching?
R matches supplied arguments to formals in three passes: exact name matching first, then partial (prefix) name matching, then positional matching for whatever remains.
Exact name match: Named arguments are bound to identically named formals first, regardless of order.
Partial name match:
An unambiguous prefix matches, e.g. verb = can match a verbose formal.
Does not apply to arguments after ..., which require exact names.
Positional match: Remaining unnamed arguments fill remaining formals left to right.
Practical advice: Rely on position only for the first one or two obvious arguments; name the rest, and avoid partial matching in production code (it is fragile).
Q68.What does invisible() do and why would a function return a value invisibly?
invisible() do and why would a function return a value invisibly?invisible(x) returns a value that is not auto-printed at the console, though it is still a normal return value you can assign or use.
What it does:
Suppresses the automatic printing that happens when a function's result is evaluated at the top level.
Wrapping the value in a call to print() or assigning it still works normally.
When to use it:
Functions called for side effects (plotting, printing, writing files) that still want to return something useful.
Enabling pipe/chaining patterns, e.g. print.* methods return their argument invisibly so x <- print(x) works.
Q69.What is the search path in R and how does attaching packages affect variable resolution?
The search path is R's ordered list of environments that are consulted when resolving a name at the top level or from the global environment. It runs from the global environment through attached packages down to the base package, and R uses the first match it finds.
Structure:
Inspect it with search(); it typically starts at .GlobalEnv and ends at package:base.
Each attached package is an environment linked in a chain.
Effect of attaching packages:
library() inserts a package's exports just after the global environment, so its functions become directly callable.
A newly attached package can mask names from earlier ones; R warns about this and resolves to the one nearer the front.
Resolving conflicts:
Use pkg::name to bypass the search path and name a package explicitly.
Note: function bodies use lexical scoping (their package's namespace) rather than the interactive search path.
Q70.How does the condition system work in R — what is the difference between message(), warning(), and stop()?
message(), warning(), and stop()?R's condition system signals structured objects up the call stack that handlers can catch. message(), warning(), and stop() signal three built-in severities: informational, non-fatal, and fatal.
message(): Signals a message condition for diagnostics; prints to stderr and execution continues.
warning():
Signals a warning condition; code continues but the issue is reported (deferred by default until the call finishes).
options(warn = 2) turns warnings into errors.
stop(): Signals an error condition and halts execution unless a handler catches it.
Underlying mechanism:
All three build condition objects (via simpleCondition family) that signalCondition() sends up the stack.
You can define custom condition classes with structure(class = c("myError", "error", "condition")) for typed handling.
Q71.How does recursion work in R, and what is the purpose of Recall()?
Recall()?Recursion is when a function calls itself to solve a problem by breaking it into smaller subproblems, with a base case to stop. Recall() provides a way to make that self-call without referring to the function by its name.
How recursion works:
Each call needs a base case (stops recursion) and a recursive case (reduces the problem).
R has no tail-call optimisation, so deep recursion risks hitting options(expressions) limits or stack overflow.
Recall():
Calls the currently executing function regardless of the name it was bound to.
Keeps recursion correct if the function is renamed, reassigned, or anonymous.
Practical note: For large iterations, prefer iterative loops or vectorised solutions for speed and safety.
Q72.What is the difference between apply(), lapply(), sapply(), and tapply()?
apply(), lapply(), sapply(), and tapply()?All are members of R's apply family for applying a function without explicit loops; they differ in what they iterate over and what they return.
apply(X, MARGIN, FUN):
Works over the rows (MARGIN = 1) or columns (MARGIN = 2) of a matrix or array.
Returns a vector, matrix, or array depending on FUN.
lapply(X, FUN): Applies FUN to each element of a list or vector and always returns a list of the same length.
sapply(X, FUN):
A user-friendly wrapper around lapply() that simplifies the result to a vector or matrix when possible.
Its return type is unpredictable; use vapply() when you need a guaranteed shape.
tapply(X, INDEX, FUN): Applies FUN to subsets of X split by one or more grouping factors (a group-by aggregation).
Q73.Why are explicit loops often discouraged in R? Describe the apply family of functions and purrr's map_* functions as idiomatic alternatives.
map_* functions as idiomatic alternatives.Explicit loops aren't slow by nature in R, but they push boilerplate (index management, result accumulation) onto you and often invite anti-patterns like growing objects. Functional iteration tools express intent (apply this to each element) more clearly and handle allocation for you.
Why loops are discouraged:
They mix intent with mechanics; readers must trace indices to see what's happening.
They encourage side effects and dynamically growing results, which is slow and error-prone.
The apply family:
lapply(): applies a function over a list/vector, always returns a list.
sapply(): like lapply() but simplifies to a vector/matrix when possible (convenient, unpredictable type).
vapply(): like sapply() with an enforced return template (type-safe).
apply(): over rows/columns of a matrix; mapply()/Map(): iterate over multiple arguments in parallel.
purrr's map_* functions:
map() returns a list; typed variants (map_dbl(), map_chr(), map_lgl()) guarantee output type or error.
Consistent argument order, formula shorthand (~ .x + 1), and map2()/pmap() for multiple inputs.
Caveat: many base operations are already vectorised (x + y, rowSums()); prefer those before any iteration tool.
Q74.Explain the concept of vector recycling in R with an example of when it occurs and its implications.
Vector recycling is R's rule for combining vectors of different lengths: the shorter vector is repeated (recycled) until it matches the length of the longer one, then the operation proceeds element-wise.
When it occurs:
Any element-wise operation on mismatched lengths: arithmetic, comparison, logical ops.
Cleanest when the longer length is an exact multiple of the shorter; otherwise you get a warning.
Implications:
Powerful: scalar operations (x * 2) work because the length-1 vector recycles across all elements.
Dangerous: silent recycling can mask bugs when lengths mismatch unintentionally.
Defensive tip: check lengths explicitly or use vctrs/tidyverse functions that error on incompatible sizes.
Q75.When would you prefer vectorisation over loops for performance in R?
Prefer vectorisation whenever the same operation applies independently to every element, because vectorised functions push the per-element loop down into compiled C code, avoiding R's interpreter overhead on each iteration.
Why it's faster:
An R-level loop interprets bytecode every iteration; a vectorised call runs one optimised C loop.
It also avoids repeated allocation and dispatch costs.
When to reach for it:
Element-wise arithmetic/logic (x + y, ifelse()).
Aggregations with built-ins (colSums(), rowMeans(), cumsum()).
When loops are fine:
Genuinely sequential logic (each step depends on the previous, e.g. some recursions).
Side-effecting work (I/O, plotting) where there's nothing to vectorise.
Q76.What is the split-apply-combine strategy in R?
Split-apply-combine is a data-analysis pattern: split the data into groups, apply a function to each group independently, then combine the results back into a single structure.
The three steps:
Split: partition by a grouping key (split(), or a group column).
Apply: run a computation per group (summary, model, transform).
Combine: bind the per-group results into a vector, list, or data frame.
Implementations in R:
Base: tapply(), aggregate(), by(), split() + lapply().
dplyr: group_by() + summarise()/mutate().
data.table: DT[, .(...), by = key].
Q77.Why is growing a vector in a loop an anti-pattern, and how does pre-allocation help?
Growing a vector element-by-element in a loop (e.g. x <- c(x, new)) is an anti-pattern because R has no in-place resize: each append allocates a new, larger vector and copies all existing elements, giving quadratic (O(n²)) cost.
Why it's slow:
Vectors are fixed-size; "appending" reallocates and copies the whole vector.
Repeated copying means total work grows with the square of the number of elements.
How pre-allocation helps:
Create the full-size container up front (numeric(n), vector("list", n)) and fill by index.
Each assignment is O(1), so the loop is O(n) overall.
Better still: use vapply()/map_dbl(), which allocate the result for you.
Q78.What is the difference between sapply() and vapply(), and why is vapply() considered safer?
sapply() and vapply(), and why is vapply() considered safer?Both apply a function over each element and simplify the result, but sapply() guesses the output type at runtime, while vapply() requires you to declare the expected type and length of each result via a template (FUN.VALUE), making it predictable.
sapply():
Convenient and interactive: simplifies to a vector, matrix, or falls back to a list.
Risk: the return type/shape depends on the data, so it can silently change (e.g. return a list instead of a vector).
vapply():
You specify a template like numeric(1) or character(1).
Errors immediately if any element's result doesn't match type or length.
Why vapply() is safer:
Guaranteed output type/shape prevents downstream surprises: essential in production and package code.
Also handles empty inputs correctly (returns the right-typed empty result).
Q79.What do the Map(), Reduce(), and Filter() functions do in R's functional programming toolkit?
Map(), Reduce(), and Filter() functions do in R's functional programming toolkit?They are R's base higher-order functions for functional-style iteration: Map() applies a function element-wise across one or more vectors/lists, Reduce() collapses a sequence into a single value via a binary function, and Filter() keeps only elements matching a predicate.
Map(f, ...):
Applies f to corresponding elements of one or more lists, returning a list.
It is a wrapper around mapply() with SIMPLIFY = FALSE, so output is always a list.
Reduce(f, x, accumulate):
Folds a vector/list with a two-argument function: Reduce(`+`, 1:4) gives 10.
Supports an init value, right-to-left folding (right = TRUE), and accumulate = TRUE to keep intermediate results.
Filter(f, x): Returns the subset of x for which the predicate f returns TRUE.
Interview note: they express intent without explicit loops; the tidyverse purrr package (map(), reduce(), keep()) offers type-stable alternatives.
Q80.What is the difference between readr functions and base R's read.csv() for reading data?
readr functions and base R's read.csv() for reading data?readr functions like read_csv() are faster, more consistent, and produce tibbles, whereas base R's read.csv() is slower and applies surprising default conversions.
Output type: read_csv() returns a tibble (nicer printing, no row names); read.csv() returns a plain data.frame.
Default behavior:
read.csv() historically used stringsAsFactors (pre-R 4.0) and mangles column names; read_csv() keeps strings as characters and preserves names.
readr guesses column types from the first rows and prints a column specification you can pin down explicitly.
Performance: readr is substantially faster on large files and shows a progress bar; data.table::fread() is faster still if speed is critical.
Consistency: readr behaves the same across locales and platforms, reducing reproducibility surprises.
Q81.Describe the tidyverse ecosystem and its core packages. What advantages does it offer for data analysis workflows?
tidyverse ecosystem and its core packages. What advantages does it offer for data analysis workflows?The tidyverse is a collection of R packages sharing a common design philosophy, grammar, and data structure (the tibble) so they work together seamlessly for the full data analysis workflow.
Core packages:
readr: import flat files into tibbles.
tidyr: reshape data into tidy form (pivot_longer(), pivot_wider()).
dplyr: transform and summarize data with verbs.
ggplot2: visualize with the grammar of graphics.
purrr: functional iteration; tibble: modern data frames; stringr and forcats: strings and factors.
Advantages:
Consistent APIs: functions take data first, return predictable types, and pipe together.
Readable, expressive code that maps closely to how you describe the analysis in words.
One install (library(tidyverse)) loads a coherent, well-documented toolkit.
Trade-off: extra dependencies and a distinct dialect to learn versus lean base R.
Q82.Explain the pipe operator (%>% vs the native |>) in R. What are its benefits and how does it improve code readability?
%>% vs the native |>) in R. What are its benefits and how does it improve code readability?The pipe passes the result on its left as the first argument to the function on its right, letting you read nested calls as a left-to-right sequence of steps. %>% comes from magrittr/tidyverse; |> is the native pipe built into R 4.1+.
Readability benefit: Turns h(g(f(x))) into x |> f() |> g() |> h(), read top-to-bottom like a recipe with no intermediate variables.
Key differences:
%>% supports the . placeholder for the piped value anywhere in the call; the native pipe's placeholder is _ and only works with named arguments (recent R).
|> is dependency-free and slightly faster; %>% is more flexible and works in older R.
Both make code composable and reduce error-prone nesting; prefer |> for new code unless you need magrittr features.
Q83.Explain the Tidy Data principle and how it relates to data manipulation in R.
Tidy data is a standard way of structuring a dataset where each variable is a column, each observation is a row, and each type of observational unit is its own table. This consistent shape is what makes tidyverse tools compose so smoothly.
The three rules:
Each variable forms a column.
Each observation forms a row.
Each observational unit forms a table.
Why it matters:
dplyr, ggplot2, and tidyr all assume this layout, so tidy data means less reshaping and fewer bugs.
Vectorized operations map naturally onto columns-as-variables.
Reshaping to tidy:
pivot_longer() gathers wide columns into key-value rows (e.g. year columns into one year column).
pivot_wider() does the reverse, spreading a variable back across columns.
Common untidy signs: variables stored in column headers, multiple variables packed in one column, or values in cell names.
Q84.How do you perform data reshaping using tidyr functions like pivot_longer() and pivot_wider()?
tidyr functions like pivot_longer() and pivot_wider()?tidyr reshapes between "long" and "wide" formats: pivot_longer() collapses many columns into key-value pairs (wide to long), and pivot_wider() spreads a key-value pair back into columns (long to wide).
pivot_longer(): wide to long:
cols selects which columns to gather; names_to and values_to name the resulting key and value columns.
Useful before plotting with ggplot2 or grouped summaries.
pivot_wider(): long to wide:
names_from supplies the new column names; values_from supplies the cell values.
They are inverses of each other.
Q85.Explain how to perform data merging/joining in R, contrasting base R's merge() with dplyr's join functions.
merge() with dplyr's join functions.Both combine tables on matching key columns; base R's merge() is a single flexible function controlled by arguments, while dplyr provides explicit, readable join verbs (inner_join(), left_join(), etc.) that are generally faster and preserve row order.
Base R merge():
Join type set by all, all.x, all.y (inner/left/right/full); keys via by.
Can reorder rows and is slower on large data.
dplyr joins:
Named by intent: inner_join(), left_join(), right_join(), full_join().
Filtering joins semi_join() and anti_join() keep/drop rows without adding columns.
by = join_by(...) specifies keys; preserves left-table row order.
Q86.What is the difference between a tibble and a data.frame?
tibble and a data.frame?A tibble is the tidyverse's modern reimagining of a data frame: it behaves like a data.frame but with safer defaults and cleaner printing.
Printing: Tibbles show only the first 10 rows and columns that fit, plus each column's type; data frames can flood the console.
Subsetting behavior: df[, 1] on a tibble always returns a tibble; a data.frame may drop to a vector unless drop = FALSE.
Safer defaults: No partial matching of column names, no automatic stringsAsFactors, and column names are left as-is.
Compatibility: A tibble is a data frame (inherits the class), so most functions accept it.
Q87.What is the difference between base R data-frame operations and the tidyverse approach?
tidyverse approach?Both operate on data frames, but base R uses bracket indexing and functions with often terse syntax, while the tidyverse offers a consistent grammar of verbs connected by pipes that reads like a sentence.
Base R:
Uses [ ], $, subset(), aggregate(); no dependencies, always available.
Non-standard evaluation is limited; column references often repeat the data name.
Tidyverse:
dplyr verbs chained with %>%/|>; refers to columns by bare name (tidy evaluation).
Consistent function naming and output types improve readability and teaching.
Trade-offs: Base R is dependency-free and stable; tidyverse is more expressive but adds packages and can change APIs.
Q88.What does the across() function do in dplyr and why was it introduced?
across() function do in dplyr and why was it introduced?across() applies the same transformation to multiple columns inside mutate() or summarise(), replacing the older scoped variants (_at, _if, _all) with one unified, tidy-select interface.
What it does:
Takes a column selection plus one or more functions and applies them column-wise.
Column selection uses tidy-select helpers like where(), starts_with(), everything().
Why it was introduced:
To remove the proliferation of summarise_at()/mutate_if() variants with one consistent idiom.
Reduces repetition and works cleanly within grouped operations.
Q89.How do separate() and unite() work in tidyr for splitting and combining columns?
separate() and unite() work in tidyr for splitting and combining columns?They are inverse operations for column values: separate() splits one column into several based on a delimiter or position, and unite() combines several columns into one.
separate(): one column to many:
col is the source; into names the new columns; sep gives the delimiter (regex or position).
Useful for splitting things like "2024-01" into year and month.
unite(): many columns to one: Names the new column, lists the source columns, and joins them with sep.
Note: Newer tidyr recommends separate_wider_delim() and related functions, but separate()/unite() remain widely used.
Q90.What is the placeholder in the magrittr pipe (.) versus the native pipe (_), and how do they differ?
.) versus the native pipe (_), and how do they differ?Both let you reference the piped value explicitly instead of passing it to the first argument, but the magrittr . is flexible and can appear anywhere/multiple times, while the native _ is deliberately restricted to a single named argument.
magrittr placeholder .:
Can be used multiple times and in any position, e.g. x %>% f(a, .) or x %>% {g(., .)}.
Very flexible but implicit rules can surprise (it still auto-inserts unless . appears as a top-level argument).
native placeholder _ (R 4.2+):
Must be passed to a named argument, e.g. x |> lm(data = _).
Can appear only once, and not as the first positional argument (that is what the pipe already fills).
No extraction on the placeholder in early versions, though _$col became allowed later.
Key difference: magrittr trades explicitness for flexibility; the native pipe favors simplicity and no dependency, enforcing stricter, more predictable usage.
Q91.How does aggregate() work in base R and how does it relate to split-apply-combine?
aggregate() work in base R and how does it relate to split-apply-combine?aggregate() splits data into groups, applies a summary function to each group, and combines the results into a data frame: it is base R's canonical split-apply-combine tool.
Split-apply-combine mapping:
Split: rows are grouped by the by list or formula variables.
Apply: the FUN argument runs on each group (e.g. mean, sum).
Combine: results are stacked back into one tidy data frame.
Two calling styles:
Formula: aggregate(mpg ~ cyl, data = mtcars, FUN = mean).
List: aggregate(mtcars$mpg, by = list(mtcars$cyl), FUN = mean).
Limitations: FUN should return a single value (or fixed-length vector) per group; more complex per-group logic is easier with dplyr::group_by() + summarise().
Q92.What is a formula object in R (the ~ notation) and how is it used beyond modelling?
~ notation) and how is it used beyond modelling?A formula is an unevaluated language object created with ~ that captures a relationship between symbols without evaluating them: it stores expressions plus the environment where they were defined, so it can be interpreted later by whatever function receives it.
Structure:
y ~ x: left side (response) and right side (predictors); a one-sided formula like ~ x has no LHS.
Operators are symbolic: +, :, * mean model terms/interactions, not arithmetic.
Modelling use: lm(mpg ~ hp + wt, data = mtcars) tells the model which columns are response and predictors.
Uses beyond modelling:
Reshaping/aggregation: aggregate(), xtabs().
Plotting with lattice/base plot(y ~ x).
As lazy-evaluation objects capturing expressions, e.g. tidyverse map() shorthands (~ .x + 1).
It carries its environment: Because a formula stores where it was created, functions can evaluate its terms with the right variables (useful for nonstandard evaluation).
Q93.How do you work with dates and times in R using Date, POSIXct, and the lubridate package?
Date, POSIXct, and the lubridate package?R represents calendar dates with Date (days since 1970-01-01) and date-times with POSIXct (seconds since the epoch, timezone-aware); lubridate wraps these in a consistent, friendly API for parsing and arithmetic.
Date: Stores whole days, no time component; created with as.Date("2024-01-15").
POSIXct vs POSIXlt:
POSIXct is a compact numeric seconds count (best for storage/data frames).
POSIXlt is a list of components (year, month, etc.), handy for extraction but bulky.
Both are timezone-aware via the tz attribute.
lubridate conveniences:
Parsing by name: ymd(), mdy(), ymd_hms().
Accessors: year(), month(), wday().
Arithmetic distinguishes period (calendar, e.g. months(1)) from duration (exact seconds, e.g. dseconds()), which matters across DST boundaries.
Q94.How does stringr help with string manipulation, and how does it compare to base R regex functions like grepl() and gsub()?
stringr help with string manipulation, and how does it compare to base R regex functions like grepl() and gsub()?stringr provides a consistent, verb-named wrapper around R's string and regex engine: every function starts with str_, takes the string as the first argument, and returns predictable types, making pipelines cleaner than base R's inconsistent argument orders.
Consistent interface: String first, pattern second, so it pipes naturally; base R varies (grepl(pattern, x) vs gsub(pattern, replacement, x)).
Common verbs: str_detect() (like grepl()), str_replace()/str_replace_all() (like sub()/gsub()), str_extract(), str_split().
Predictable return types & vectorization: Returns fixed types and handles NA consistently; base functions can differ (regmatches() is awkward for extraction).
When base R is fine: grepl(), gsub(), regmatches() are dependency-free and identical under the hood; stringr mostly wins on readability and consistency.
Q95.Explain the concept of namespaces in R packages and how the :: operator is used.
:: operator is used.A namespace is a package's private environment that controls which of its objects are visible externally (exported) versus internal, letting packages avoid name clashes; the :: operator reaches directly into a package's exported objects.
What a namespace does:
Separates exports (public API listed in NAMESPACE) from internal helper functions.
Fixes imports so a package always finds the functions it depends on, even if another package defines the same name.
The :: operator:
Accesses an exported object as pkg::name without attaching the whole package with library().
Disambiguates clashes, e.g. dplyr::filter() vs stats::filter().
Why it matters: it makes code explicit and robust to load order, at a tiny lookup cost.
Q96.What is the difference between library() and require()?
library() and require()?Both load and attach a package, but they differ in how they report failure: library() throws an error if the package is missing, while require() returns TRUE/FALSE and only warns.
library(): Fails loudly with an error, which stops a script: best for scripts and reproducible code.
require():
Returns a logical, so it's designed for conditional use inside if checks.
Danger: if used at the top of a script and the package is missing, execution continues and you get confusing later errors.
Rule of thumb: use library() normally; use require() only when you genuinely branch on availability.
Q97.What is the difference between :: and ::: for accessing package namespaces?
:: and ::: for accessing package namespaces?Both reach into a package namespace, but :: accesses only exported (public) objects while ::: reaches internal (unexported) ones.
pkg::name: Gets the package's public API: the intended, stable way to use another package's functions.
pkg:::name:
Gets internal objects not exported in NAMESPACE.
Fragile: internals can change or vanish between versions without notice, and CRAN discourages it.
Guidance: use :: in shared code; reserve ::: for debugging or a package's own internal tests.
Q98.What is the difference between attaching and loading a package in R?
Loading brings a package's namespace into memory so its code is available; attaching additionally puts the package on the search path so you can call its exported functions by bare name.
Loading:
Registers the namespace so objects can be reached via ::; triggered by loadNamespace() or the first :: access.
A dependency listed under Imports is loaded but not attached.
Attaching: Adds the package to the search() path so funcname works without a prefix; done by library().
Consequence: many exported bare names on the search path can mask each other, which is why package internals prefer explicit imports over attaching.
Q99.What is Bioconductor and how does it differ from CRAN?
Bioconductor is a separate repository and community focused on bioinformatics and genomics; it differs from CRAN in its domain focus, release cadence, and its own installer.
Focus: Specialized packages for high-throughput biological data (genomics, sequencing) with shared core data classes.
Release model: Coordinated releases twice a year, versioned against a specific R version, unlike CRAN's continuous updates.
Installation: Installed via the BiocManager package rather than plain install.packages().
Q100.What is ggplot2's grammar of graphics and how do aes, geoms, scales, facets, and themes fit together?
ggplot2's grammar of graphics and how do aes, geoms, scales, facets, and themes fit together?The grammar of graphics is the idea that any statistical plot can be built by layering independent components: you map data to visual properties, choose geometric shapes to draw, then control how those properties are scaled, partitioned, and styled. ggplot2 implements this so plots are composed additively with +.
Data + aesthetics (aes()):
Maps columns to visual channels: x, y, color, size, shape.
Mapping (inside aes()) is data-driven; setting a constant goes outside aes().
Geoms:
The geometric layer that actually draws: geom_point(), geom_line(), geom_bar().
You can stack multiple geoms in one plot.
Scales: Control how data values translate to aesthetic values: axis breaks, color palettes, log transforms (scale_x_log10(), scale_color_brewer()).
Facets: Split data into small multiples by a variable: facet_wrap(), facet_grid().
Themes: Non-data styling: fonts, gridlines, background (theme_minimal(), theme()).
The power is orthogonality: each layer is independent, so you swap a geom or scale without rewriting the whole plot.
Q101.When would you use base R graphics functions versus ggplot2 for data visualization?
ggplot2 for data visualization?Use base R graphics for quick, throwaway exploratory plots and simple diagnostics; use ggplot2 for polished, multi-layered, publication-quality visuals driven by tidy data.
Base R graphics:
Fast one-liners (plot(), hist(), boxplot()) with no dependencies.
Uses an imperative "pen on paper" model: you draw, then add elements (lines(), points()).
Good for quick checks and when plotting arbitrary vectors, not data frames.
ggplot2:
Declarative: you describe mappings and layers, it handles rendering.
Excels at grouping, faceting, legends, and consistent theming with little code.
Expects tidy data (one observation per row); reshaping first is often needed.
Rule of thumb: Exploratory speed and no dependencies: base R. Structured, layered, shareable graphics: ggplot2.
Q102.How is ggplot2 used for data visualization?
ggplot2 used for data visualization?ggplot2 is used to build visualizations declaratively: you take a tidy data frame, map its columns to visual aesthetics, and add layers that draw and refine the plot, composing everything with +.
Typical workflow:
Supply tidy data and mappings via ggplot(data, aes(...)).
Choose one or more geoms for the plot type.
Adjust scales, facets, labels, and theme as needed.
Common plot types:
Distributions: geom_histogram(), geom_boxplot().
Relationships: geom_point(), geom_smooth().
Comparisons and trends: geom_bar(), geom_line().
Strengths:
Automatic legends, color grouping, and small-multiple faceting from a single grouping variable.
Consistent, reusable code: swap a geom or theme without rebuilding the plot.
Q103.What is the difference between generic functions and methods in R's OOP systems?
A generic function is the dispatcher (the public entry point) and a method is the concrete implementation chosen for a particular class. You call the generic; R inspects the argument(s) and runs the matching method.
Generic function:
A single name (print, summary, plot) whose job is to dispatch, not to do the work.
In S3 it typically calls UseMethod(); in S4 it calls standardGeneric().
Method: The class-specific function actually executed, e.g. print.data.frame (S3) or a method registered by setMethod() (S4).
Relationship: one generic, many methods: Adding support for a new class means writing a new method, never editing the generic: this is how R achieves polymorphism.
Q104.Which packages in R are used for data mining?
R has a rich ecosystem for data mining spanning classification, clustering, association rules, and text mining, most of which are curated in the CRAN Task View for Machine Learning.
General modeling and ML frameworks:
caret and tidymodels: unified interfaces for training, tuning, and resampling across many algorithms.
mlr3: modern object-oriented ML pipeline framework.
Algorithm-specific packages:
rpart and randomForest: trees and ensembles.
e1071 (SVM, naive Bayes), xgboost and glmnet (boosting, regularized regression).
cluster: k-means, PAM, hierarchical clustering.
Specialized tasks:
arules: association rule mining (Apriori, Eclat).
tm and text2vec: text mining and NLP.
nnet, keras, tensorflow: neural networks and deep learning.
Q105.How do you call statistical tests like t.test() in R and interpret the returned result object?
t.test() in R and interpret the returned result object?You call a test like t.test() by passing data (two vectors, or a formula plus data
Q106.How do you fit a model with lm() or glm() in R, and how do the formula syntax and summary()/coef()/predict() work?
lm() or glm() in R, and how do the formula syntax and summary()/coef()/predict() work?You fit models with a formula object describing the relationship: lm() for linear (Gaussian) regression and glm() for generalized linear models (specifying a family). The returned model object is then interrogated with helpers like summary(), coef(), and predict().
Formula syntax: y ~ x1 + x2:
LHS is the response, RHS the predictors; an intercept is implicit (drop it with + 0 or - 1).
Operators are special: x1:x2 is an interaction, x1*x2 expands to main effects plus interaction, and I(x^2) protects arithmetic so it is taken literally.
Factors are automatically expanded into dummy/contrast columns.
lm() vs glm():
lm() assumes normally distributed errors, fit by least squares.
glm() adds a family and link, e.g. family = binomial for logistic regression or poisson for counts.
Inspecting the fit:
summary(): coefficients table (estimates, standard errors, p-values), plus R-squared (lm) or deviance/AIC (glm).
coef(): the estimated coefficient vector alone.
predict(): fitted values for new data via newdata=; for glm use type = "response" to get the response scale rather than the link scale.
Related extractors: residuals(), fitted(), confint(), and anova().
Q107.How do R's random-generation and distribution functions like the r/d/p/q family and set.seed work?
r/d/p/q family and set.seed work?Q108.What are knitr chunk options and how do parameterised R Markdown reports work?
knitr chunk options and how do parameterised R Markdown reports work?Q109.What is an environment in R and how does it differ from a list?
list?Q110.What do do.call, match.arg, and on.exit do in R?
do.call, match.arg, and on.exit do in R?Q111.What is a promise in R and what does force() do?
force() do?Q112.What does it mean that R passes function arguments by value, and how do environments provide reference semantics as an exception?
Q113.Explain how lazy evaluation works for function arguments in R and how it can impact performance and control flow.
Q114.Explain the concept of lexical scoping in R and how environments affect variable access within functions.
Q115.What does the <<- operator do and how does it interact with enclosing environments?
<<- operator do and how does it interact with enclosing environments?Q116.How do the get(), exists(), and assign() functions let you work with environments programmatically?
get(), exists(), and assign() functions let you work with environments programmatically?Q117.How do tryCatch() and withCallingHandlers() work for error handling in R?
tryCatch() and withCallingHandlers() work for error handling in R?Q118.What are closures in R? Provide an example of their use and explain their benefits.
Q119.What is memoization and how would you implement it using closures in R?
Q120.What is the difference between dplyr and data.table for data manipulation, and when would you choose one over the other for large datasets?
dplyr and data.table for data manipulation, and when would you choose one over the other for large datasets?Q121.Describe the data.table syntax (DT[i, j, by], := by reference, keys) and its advantages for performance with large datasets.
data.table syntax (DT[i, j, by], := by reference, keys) and its advantages for performance with large datasets.Q122.What are list-columns and nested data frames in R, and when are they useful?
Q123.What are the essential components of an R package (DESCRIPTION, NAMESPACE, R/, man/)?
DESCRIPTION, NAMESPACE, R/, man/)?Q124.What is the S3 object system and how does method dispatch via UseMethod work?
S3 object system and how does method dispatch via UseMethod work?Q125.How do Reference Classes (R5) and R6 differ from S3 and S4, and when would you use each?
R5) and R6 differ from S3 and S4, and when would you use each?Q126.Explain R's S3 and S4 object-oriented programming systems. What are their key differences and when would you use one over the other?
S3 and S4 object-oriented programming systems. What are their key differences and when would you use one over the other?Q127.How does inheritance work through the class vector in S3, and what does NextMethod do?
class vector in S3, and what does NextMethod do?Q128.What is the S4 object system and how do setClass, setGeneric, and setMethod work?
S4 object system and how do setClass, setGeneric, and setMethod work?Q129.What is multiple dispatch in S4?
S4?Q130.How does operator overloading work in the S3 system (e.g. defining print or + methods for a class)?
S3 system (e.g. defining print or + methods for a class)?Q131.Describe techniques for optimizing R code performance and memory usage when working with large datasets.
Q132.Explain R's copy-on-modify semantics. When do copies of objects actually occur and how can this impact performance and memory?
Q133.How does R handle memory management, and what strategies help manage memory effectively with large objects?
Q134.At a conceptual level, how can interfacing with compiled code (e.g., C++ via Rcpp) improve the performance of R code?
Rcpp) improve the performance of R code?Q135.Explain the concept of parallel processing in R and how to use it.
Q136.What are the performance and memory trade-offs between a data.frame, a matrix, and a data.table?
data.frame, a matrix, and a data.table?Q137.How do you profile R code with Rprof, and what is byte-compilation?
Rprof, and what is byte-compilation?Q138.How would you design a hybrid workflow that efficiently integrates both R and Python, and how would you divide responsibilities between them?
Q139.How does R's garbage collection work and when would you call gc()?
gc()?Q140.How do you ensure reproducibility in R projects concerning package versions and dependencies? Discuss tools like renv or packrat.
Q141.What is non-standard evaluation (NSE) in R, and where is it commonly used?
Q142.What is tidy evaluation, and what are quosures and quasiquotation in the rlang framework?
rlang framework?