Skip to content

R Programming Interview Questions for 1 Year Experience

40 questions with answers for candidates with 1 year of experience — 17 easy, 22 medium, 1 hard.

What interviewers expect: 1 year experience

With one year of experience, expect deeper wrangling questions: joins, window functions, reshaping, handling dates and missing values, and debugging pipelines. Interviewers ask about reports you automated and how you validated numbers. Basic hypothesis testing and regression interpretation are common, along with SQL and Excel integration. Expect a practical data-cleaning task in most rounds.

This set is weighted towards R Basics and Data Types (8), Data Structures in R (7), Data Visualization with ggplot2 (7), Data Wrangling with dplyr and tidyr (5).

Joins and window functions Report automation Hypothesis testing Data validation
Solved at this levelStart 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

How do you add logging to a production R script?

Save to ▾
Show answer
The logger package gives levelled, timestamped logs written to the console or a file. library(logger) log_appender(appender_file('logs/etl.log')) log_threshold(INFO) log_info('ETL started') res <- tryCatch({ df <- load_orders() log_info('Loaded {nrow(df)} rows') df }, error = function(e) { log_error('Load failed: {conditionMessage(e)}') quit(status = 1) }) log_info('ETL finished')
02

Dates in your file look like 25/12/2025 and as.Date() returns NA. What is wrong and how do you fix it?

Save to ▾
Show answer
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.
03

Explain the difference between NA, NULL and NaN in R.

Save to ▾
Show answer
NA means a missing value and has a type, such as NA_integer_ or NA_character_. NULL means the absence of an object, has length 0 and disappears when combined with c(). NaN means not a number, the result of undefined maths like 0/0. is.na() returns TRUE for both NA and NaN, while is.nan() is TRUE only for NaN. For example, length(c(1, NULL, 3)) is 2 but length(c(1, NA, 3)) is 3.
04

What is a list-column and why is it useful?

Save to ▾
Show answer
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.
05

How do you calculate ROC AUC and plot an ROC curve in R?

Save to ▾
Show answer
yardstick in tidymodels or pROC compute AUC from predicted probabilities. library(yardstick) preds <- tibble(truth = factor(test$churned, levels = c('1', '0')), .pred_1 = test$prob) roc_auc(preds, truth, .pred_1) roc_curve(preds, truth, .pred_1) %>% autoplot() # with pROC library(pROC) r <- roc(test$churned, test$prob) auc(r); plot(r)
06

The same 40 lines of cleaning code are copied into ten scripts. What would you do?

Save to ▾
Show answer
I would extract the logic into well-named functions with arguments for the parts that differ, then move them into one shared file loaded with source() or, better, a small internal R package. A package gives documentation with roxygen2, tests with testthat and versioning, so every script uses the same tested logic. Fixing a bug then happens in one place. I would migrate the scripts gradually and compare outputs to confirm nothing changed.
07

Tell me about a chart or visualization that changed a business decision.

Save to ▾
Show answer
Situation: the operations team believed late deliveries were spread evenly across the week. Task: I was asked to review delivery data. Action: in R I built a heatmap of late deliveries by weekday and hour with ggplot2, which showed a sharp cluster on Monday mornings linked to weekend order backlog. Result: management added a Sunday evening shift, and late deliveries dropped by about 18 percent the next quarter.
08

How do you handle missing values in calculations in R?

Save to ▾
Show answer
Most summary functions return NA if any value is missing, so pass na.rm = TRUE or remove NAs first. x <- c(10, NA, 30, 40) mean(x) # NA mean(x, na.rm = TRUE) # 26.67 sum(is.na(x)) # count missing: 1 x[!is.na(x)] # drop NAs x[is.na(x)] <- median(x, na.rm = TRUE) # impute df[complete.cases(df), ] # rows with no NA
09

What is the difference between variance and standard deviation?

Save to ▾
Show answer
Variance is the average squared deviation from the mean, and standard deviation is its square root. Because variance is in squared units, standard deviation is easier to interpret since it uses the same units as the data. In R, var() and sd() both use the sample formula with n - 1 in the denominator. For example, delivery times with mean 30 minutes and SD 5 minutes are far more consistent than with SD 15.
10

Salary data has a few extreme values that distort averages. How do you handle them?

Save to ▾
Show answer
First I investigate whether they are data errors, such as an extra zero, or genuine high earners. I flag outliers with the IQR rule, values beyond Q1 - 1.5 IQR or Q3 + 1.5 IQR, or with percentiles. Errors I fix or remove with documentation. Genuine values I keep, but I report the median alongside the mean, or winsorize at the 1st and 99th percentiles for modelling. The choice depends on the business question.
11

A customer table has multiple records per customer. How do you keep only the latest record for each?

Save to ▾
Show answer
I group by customer_id and keep the row with the latest updated_at using slice_max(updated_at, n = 1, with_ties = FALSE), then ungroup. An alternative is arrange(desc(updated_at)) followed by distinct(customer_id, .keep_all = TRUE). I check that updated_at is a proper date-time and has no NAs, since missing timestamps would be dropped or mis-sorted. Finally I confirm that n_distinct(customer_id) equals the number of rows.
12

How do you check whether data is normally distributed in R?

Save to ▾
Show answer
Combine visual checks with formal tests, because tests become oversensitive with large samples. hist(x, breaks = 30) qqnorm(x); qqline(x, col = 'red') shapiro.test(x) # works for n between 3 and 5000 library(ggplot2) ggplot(df, aes(sample = x)) + stat_qq() + stat_qq_line() # for model residuals plot(lm_fit, which = 2)
13

Explain the d, p, q and r functions for probability distributions in R.

Save to ▾
Show answer
Each distribution has four functions: d for density, p for cumulative probability, q for quantiles and r for random draws. dnorm(0) # density at 0 pnorm(1.96) # P(Z <= 1.96) = 0.975 qnorm(0.975) # 1.96 rnorm(5, mean = 50, sd = 10) dbinom(3, size = 10, prob = 0.2) # exactly 3 successes ppois(2, lambda = 4) # P(X <= 2) qt(0.975, df = 20) # t critical value
14

How do you create interactive charts in R?

Save to ▾
Show answer
plotly's ggplotly() converts an existing ggplot into an interactive chart with hover tooltips, zoom and legend toggling. ggiraph adds interactive tooltips and selection to ggplot geoms with fine control. highcharter and echarts4r wrap JavaScript charting libraries, and leaflet builds interactive maps. These outputs work in R Markdown or Quarto HTML reports and Shiny apps. For static PDF reports, standard ggplot2 is still the better choice.
15

Bars in your chart appear in alphabetical order instead of by value. How do you fix it?

Save to ▾
Show answer
ggplot2 orders discrete axes by factor levels, which default to alphabetical. I reorder the factor by the value with forcats: aes(x = fct_reorder(city, sales), y = sales), and add coord_flip() or put the category on the y-axis for long labels. For a fixed custom order, such as months or ratings, I set levels explicitly with factor(x, levels = c(...)). fct_infreq() orders by frequency for count bars.
16

Why did you choose to learn R?

Save to ▾
Show answer
I chose R because I enjoy working with data and statistics, and R is designed exactly for that. During my coursework I used it for a project analysing student performance, where dplyr and ggplot2 helped me move from raw data to clear insights quickly. I like that results are reproducible with R Markdown. I am also learning SQL and basic Python, so I can work comfortably in a mixed team and pick the right tool for each task.
17

What is a factor in R and when would you use one?

Save to ▾
Show answer
A factor stores categorical data as integer codes with a set of labels called levels. Factors are used for variables like gender, city or rating, and modelling functions such as lm() turn them into dummy variables automatically. Ordered factors, created with factor(x, levels = c('Low', 'Medium', 'High'), ordered = TRUE), support comparisons. A common pitfall is as.numeric() on a numeric factor, which returns codes; use as.numeric(as.character(f)) instead.
18

What does the ... (dots) argument do in an R function?

Save to ▾
Show answer
The dots let a function accept any number of additional arguments and pass them on to another function. For example, my_plot <- function(df, ...) ggplot(df, aes(x, y)) + geom_point(...) lets callers pass colour or size without declaring them. You can capture dots with list(...) or count them with ...length(). The downside is that misspelled argument names are silently ignored, so document them and validate with rlang::check_dots_used() in packages.
19

What is the Central Limit Theorem and why is it important?

Save to ▾
Show answer
The Central Limit Theorem says that the distribution of sample means approaches a normal distribution as sample size grows, roughly beyond 30, regardless of the population's shape, provided observations are independent with finite variance. It is why t-tests, confidence intervals and A/B test calculations work on non-normal data such as order values. You can demonstrate it in R by repeatedly sampling from rexp() and plotting a histogram of the means.
20

Finance says 120 transactions are missing from your report compared with their system. How do you find them?

Save to ▾
Show answer
I load both datasets and standardise the key, for example trimming spaces and matching data types for transaction_id. Then anti_join(finance, report, by = 'transaction_id') lists transactions in finance but not in my report, and the reverse anti_join shows extras. I examine the missing rows for patterns such as a date range, status or filter in my code. Usually the cause is a timezone cut-off or an excluded status.
21

Code reviews show inconsistent R code style across the team. How would you standardise it?

Save to ▾
Show answer
I would adopt the tidyverse style guide as the team standard, then automate it rather than relying on reviewers. styler reformats code automatically, including an RStudio add-in, and lintr flags issues such as long lines, unused variables and inconsistent naming. I add lintr to a pre-commit hook or a GitHub Actions check so pull requests are checked automatically. A short template for new scripts and projects helps new joiners follow the same structure.
22

What is a tibble and how does it differ from a base data frame?

Save to ▾
Show answer
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.
23

How do you customise scales, labels and themes in ggplot2?

Save to ▾
Show answer
Scales control how data maps to visuals, and themes control non-data elements. p + scale_y_continuous(labels = scales::label_percent()) + scale_fill_brewer(palette = 'Set2') + labs(title = 'Conversion by Channel', subtitle = 'FY 2025-26', caption = 'Source: CRM') + theme_minimal(base_size = 12) + theme(legend.position = 'bottom', plot.title = element_text(face = 'bold'), panel.grid.minor = element_blank())
24

Tell me about a time you automated a manual report.

Save to ▾
Show answer
Situation: my team spent two days every month building a sales report in Excel. Task: I was asked to reduce the effort. Action: I wrote an R script that pulled data from the database with DBI, cleaned it with dplyr, created charts with ggplot2 and rendered a Quarto report scheduled through cron. Result: the report ran in ten minutes, copy-paste errors disappeared and the team used the saved time for deeper analysis.
25

Which chart types would you use for comparing categories, trends and distributions?

Save to ▾
Show answer
For comparing categories I use a bar chart, sorted by value, or a dot plot when there are many categories. For trends over time I use a line chart with time on the x-axis. For distributions I use histograms or density plots for one variable and boxplots or violin plots to compare groups. For relationships between two numeric variables I use a scatter plot. I avoid pie charts beyond three or four slices.
26

What is the difference between if, ifelse() and dplyr's if_else()?

Save to ▾
Show answer
if is a control-flow statement that checks a single TRUE or FALSE value and runs one branch, used for program logic. ifelse() is vectorized and returns a vector of the same length as the condition, used for transforming data. dplyr::if_else() is a stricter vectorized version that requires both outputs to have the same type, preserves classes like dates and has a missing argument for NA conditions, making it safer than ifelse().
27

What is renv and why should you use it?

Save to ▾
Show answer
renv is a package that creates a project-specific library and records exact package versions in a renv.lock file. renv::init() sets up the project, renv::snapshot() updates the lockfile and renv::restore() installs the same versions on another machine or server. This prevents code from breaking when packages update, makes analysis reproducible months later and is essential before deploying scripts or Shiny apps to production.
28

Your analysis gives slightly different results every time you run it. How do you make it reproducible?

Save to ▾
Show answer
Functions like sample(), rnorm() and random train-test splits depend on the random number generator. I call set.seed(42) at the start of the script so the same random sequence is generated every run, which lets reviewers reproduce results. For parallel code I use reproducible streams, for example future with seed = TRUE. I also record the R version, because the default sampling algorithm changed in R 3.6.0 and can change results between versions.
29

What is the difference between errors, warnings and messages in R?

Save to ▾
Show answer
An error, raised with stop(), halts execution because something cannot continue. A warning, raised with warning(), lets code continue but signals a possible problem, such as NAs introduced by coercion. A message, from message(), is informational, such as progress updates. Messages go to stderr, so they can be suppressed with suppressMessages() without hiding results. Use print() or cat() for output the user requested, not for diagnostics.
30

What is vectorization in R and why does it matter?

Save to ▾
Show answer
Vectorization means applying an operation to a whole vector at once instead of looping over elements. Most R functions, like +, sqrt() and ifelse(), are vectorized and implemented in C, so they are much faster than R-level for loops. For example, prices * 1.18 adds 18 percent GST to every price in one step. Writing vectorized code is the first optimization an R developer should try before parallel processing or Rcpp.
31

How do you create, modify and combine lists in R?

Save to ▾
Show answer
Lists are built with list(), modified by name and combined or flattened when needed. emp <- list(name = 'Asha', skills = c('R', 'SQL'), exp = 3) emp$city <- 'Pune' # add element emp[['exp']] <- 4 # update emp$skills <- NULL # remove names(emp) parts <- lapply(1:3, function(i) data.frame(id = i, sq = i^2)) do.call(rbind, parts) # combine data frames unlist(list(a = 1, b = list(c = 2))) # flatten
32

In your regression, coefficient signs look wrong and standard errors are huge. What might be the problem?

Save to ▾
Show answer
This is a classic sign of multicollinearity, where predictors are highly correlated, for example total spend and online spend. The model cannot separate their effects, so coefficients become unstable. I check correlations and the variance inflation factor with car::vif(); values above 5 or 10 are a concern. Solutions are removing or combining correlated variables, using principal components or ridge regression. Prediction accuracy may be fine, but interpretation is unreliable.
33

What is the grammar of graphics in ggplot2?

Save to ▾
Show answer
The grammar of graphics describes a plot as layers built from components: data, aesthetic mappings that link variables to visual properties like x, y and colour, geoms that draw shapes, stats that transform data, scales, coordinate systems, facets and themes. In ggplot2 you start with ggplot(data, aes(x, y)) and add layers with +, such as geom_point(). This makes complex charts systematic and easy to modify.
34

Tell me about the messiest dataset you have cleaned.

Save to ▾
Show answer
Situation: I received three years of vendor invoices from different branches in Excel files with inconsistent headers, merged cells and dates in four formats. Task: build one clean table for spend analysis. Action: I used readxl to read all sheets, janitor::clean_names() to standardise headers, lubridate to parse dates and a mapping table for vendor name variants. I wrote validation checks for totals. Result: a clean dataset of 180,000 rows that finance now refreshes monthly.
35

How do you manage working directories and file paths in an R project?

Save to ▾
Show answer
getwd() shows and setwd() changes the working directory, but a hardcoded setwd() breaks on other machines. RStudio projects with the here package build paths relative to the project root. getwd() library(here) sales <- read.csv(here('data', 'sales.csv')) write.csv(summary_df, here('output', 'summary.csv'), row.names = FALSE) file.exists(here('data', 'sales.csv')) list.files(here('data'), pattern = 'csv$')
36

What is data.table and when would you use it?

Save to ▾
Show answer
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.
37

What is the tidyverse?

Save to ▾
Show answer
The tidyverse is a collection of R packages that share a common design and grammar for data science. Core packages include readr for importing, dplyr for transformation, tidyr for reshaping, ggplot2 for visualization, purrr for functional programming, stringr for text, forcats for factors and lubridate for dates. library(tidyverse) loads the core set. Its consistent function names and the pipe make analysis code readable, which is why most R analytics teams use it.
38

What is a data frame in R?

Save to ▾
Show answer
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.
39

How is a matrix different from a data frame?

Save to ▾
Show answer
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.
40

What is the difference between base R graphics and ggplot2?

Save to ▾
Show answer
Base graphics use functions like plot(), hist() and barplot() that draw directly on a device, and you add elements with lines() or legend() step by step. They are quick for exploration. ggplot2 builds plots as objects from layers using the grammar of graphics, handles legends and facets automatically and is easier to style consistently. Base plots are fine for quick checks, while ggplot2 is preferred for reports and publications.

Frequently asked questions

What is asked in R Programming interviews for 1 year of experience?

With one year of experience, expect deeper wrangling questions: joins, window functions, reshaping, handling dates and missing values, and debugging pipelines. Interviewers ask about reports you automated and how you validated numbers. Basic hypothesis testing and regression interpretation are common, along with SQL and Excel integration. Expect a practical data-cleaning task in most rounds.

How many questions should I practise before a R Programming interview?

Work through all 40 questions here, then the company-wise sets for the employers you are targeting. Quality matters more than count: be able to explain why each answer is right.

Which topics matter most for 1 year of experience?

Focus first on Joins and window functions, Report automation, Hypothesis testing, Data validation.