Skip to content

American Express R Programming Interview Questions & Answers

Curated interview practice questions with answers. These are practice scenarios, not a verified list of past interview questions.

About American Express hiring for R Programming roles

American Express is a global payments and card company offering charge and credit cards, travel services and merchant acquiring. Its India centres in Gurugram and Bengaluru support technology, risk, analytics and servicing. It hires for software engineers, QA engineers, data analysts, data scientists and credit risk analysts.

For R Programming roles, this American Express practice set focuses most on Data Wrangling with dplyr and tidyr (5), Modelling and Machine Learning in R (5), Reports, Shiny and Production R (5), Data Structures in R (5). It has 7 easy, 22 medium, 1 hard questions, so you can start easy and work up to the harder ones.

Company type
Banking & finance
Headquarters
New York, USA
Main India offices
Gurugram, Bengaluru

American Express R Programming interview process

  1. Online assessment (aptitude + coding or analytics)
  2. Technical round
  3. Case or domain round
  4. Hiring manager round
  5. HR round

Typical pattern based on public candidate experiences. Rounds vary by role, team and year.

Solved for American ExpressStart 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 would you impute missing values differently for each group?

Save to ▾
Show answer
I group by the relevant category, such as product category, and replace NAs with that group's median: group_by(category) %>% mutate(price = coalesce(price, median(price, na.rm = TRUE))) %>% ungroup(). Group medians are more realistic than a global value. I also add a flag column marking imputed rows so models and reviewers can see them. If a whole group is missing, I fall back to the overall median, and for important features I consider model-based imputation.
02

Your data is heavily skewed and the sample is small. Can you still use a t-test?

Save to ▾
Show answer
With small, heavily skewed samples the t-test's normality assumption is doubtful. I would check with a histogram, Q-Q plot or shapiro.test(). Options are a non-parametric test, wilcox.test() for two groups or kruskal.test() for more, a log transformation if the data is right-skewed and positive, or a bootstrap confidence interval for the difference in means. With large samples, the Central Limit Theorem usually makes the t-test acceptable.
03

How do you perform k-means clustering in R?

Save to ▾
Show answer
Scale features first, choose k using the elbow or silhouette method, then fit. library(factoextra) X <- scale(customers[, c('recency', 'frequency', 'monetary')]) fviz_nbclust(X, kmeans, method = 'wss') # elbow fviz_nbclust(X, kmeans, method = 'silhouette') set.seed(42) km <- kmeans(X, centers = 4, nstart = 25) customers$segment <- km$cluster aggregate(cbind(recency, frequency, monetary) ~ segment, data = customers, FUN = mean)
04

Reading a 2 GB CSV file with read.csv() is very slow. What would you do?

Save to ▾
Show answer
read.csv() is single-threaded and guesses types slowly. I would switch to data.table::fread() or readr::read_csv(), which are many times faster and multi-threaded. I would read only the needed columns with the select argument and set column types explicitly. If the file is reused, I convert it once to a binary format like Parquet with the arrow package, which loads in seconds and supports reading just a subset of columns.
05

How would you compare R and Python for a data role?

Save to ▾
Show answer
R is strongest for statistics, exploratory analysis, visualization and reproducible reporting, with mature packages for biostatistics, econometrics and survey analysis. Python is a general-purpose language that is stronger for production software, deep learning and web integration. Many teams use both: R for analysis and reporting, Python for pipelines and deployment. In an interview, avoid language wars and explain that the choice depends on the team's stack, the problem and who maintains the code.
06

How do you reshape data between wide and long formats in R?

Save to ▾
Show answer
tidyr's pivot_longer() turns columns into rows and pivot_wider() does the reverse. library(tidyr) # wide: product, Jan, Feb, Mar long <- sales_wide %>% pivot_longer(cols = Jan:Mar, names_to = 'month', values_to = 'sales') wide <- long %>% pivot_wider(names_from = month, values_from = sales, values_fill = 0)
07

How do you generate the same report for each of 20 regions automatically?

Save to ▾
Show answer
Use a parameterized Quarto or R Markdown report and render it in a loop. # report.qmd header: # params: # region: 'North' # then use params$region in the code regions <- unique(sales$region) purrr::walk(regions, function(r) { quarto::quarto_render( 'report.qmd', execute_params = list(region = r), output_file = paste0('report_', r, '.html') ) })
08

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.
09

How do you write unit tests for an R function?

Save to ▾
Show answer
testthat organises tests into files under tests/testthat/ using expectations. # tests/testthat/test-gst.R test_that('gst_price adds 18 percent by default', { expect_equal(gst_price(100), 118) expect_equal(gst_price(c(100, 200)), c(118, 236)) }) test_that('gst_price rejects text input', { expect_error(gst_price('abc'), 'numeric') }) # run all tests devtools::test()
10

What is R Markdown and why is it useful?

Save to ▾
Show answer
R Markdown is a file format that combines narrative text written in Markdown with R code chunks. When rendered with knitr, the code runs and its output, such as tables and charts, is inserted into an HTML, PDF or Word document. This makes reports reproducible: when data changes, you re-render instead of copying charts manually. It is used for monthly reports, research papers, client deliverables and teaching material.
11

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.
12

What is the difference between Pearson and Spearman correlation?

Save to ▾
Show answer
Pearson correlation measures the strength of a linear relationship between two numeric variables and is sensitive to outliers. Spearman correlation is computed on ranks, so it measures monotonic relationships and is robust to outliers and non-normal data. In R, cor(x, y, method = 'spearman') and cor.test() compute them. For example, ad spend and sales with diminishing returns may show a moderate Pearson value but a high Spearman value.
13

Explain the different types of joins in dplyr.

Save to ▾
Show answer
left_join() keeps all rows of the left table and adds matching columns from the right, inner_join() keeps only matching rows, right_join() keeps all rows of the right table and full_join() keeps all rows from both, filling NA where there is no match. Keys are given with by = join_by(customer_id) or by = c('id' = 'cust_id') for different names. Left joins are most common when enriching a fact table with lookup details.
14

How do you interpret the summary output of an lm() model?

Save to ▾
Show answer
Each coefficient is the expected change in the outcome for a one-unit increase in that predictor, holding others constant. The p-value tests whether the coefficient differs from zero. R-squared is the share of variance explained, and adjusted R-squared penalizes extra predictors. Residual standard error shows typical prediction error in outcome units. The F-statistic tests whether the model beats an intercept-only model. For factors, coefficients are differences from the reference level.
15

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.
16
Save to ▾
Show answer
plumber turns R functions into REST API endpoints using special comments. You annotate a function with #* @get /predict and its arguments become query parameters, then run the API with pr_run(). Other systems, such as a Java web app or a Python service, can call the R model over HTTP and receive JSON. It is commonly used to serve model predictions, and it can be deployed in Docker or on Posit Connect.
17

Show different ways to index vectors and data frames in R.

Save to ▾
Show answer
R indexes from 1 and supports positive, negative, logical and name-based indexing. x <- c(a = 10, b = 20, c = 30, d = 40) x[2] # 20 x[-1] # drop first x[c('a', 'd')] # by name x[x > 15] # logical filter which(x > 15) # positions df[df$age > 30, c('name', 'city')] df[order(-df$salary), ][1:5, ] # top 5 salaries
18

Your model has R-squared 0.92 on training data but 0.55 on test data. What do you do?

Save to ▾
Show answer
The gap indicates overfitting or data leakage. I first check for leakage, such as a feature computed using future information or the target itself, or duplicate records across train and test. Then I simplify the model, add regularization, reduce features or tune hyperparameters with cross-validation instead of a single split. If data is time-based, I make sure the split is chronological. I compare against a simple baseline to judge real improvement.
19

Your R script works on your laptop but fails on a colleague's machine with 'could not find function'. What do you check?

Save to ▾
Show answer
First I check that the package providing the function is installed and loaded with library() at the top of the script, not only in my interactive session. Then I compare R and package versions using sessionInfo(), because functions get renamed or deprecated. To prevent this, I use renv to snapshot exact package versions into a lockfile, so the colleague runs renv::restore() and gets the same environment. Namespacing calls like dplyr::filter() also avoids masking conflicts.
20

What is an array in R?

Save to ▾
Show answer
An array is a multi-dimensional generalization of a matrix, created with array(data, dim = c(rows, cols, layers)). All elements share one type. For example, array(1:24, dim = c(2, 3, 4)) has four layers of 2 by 3 matrices, and you index with arr[1, 2, 3]. Arrays are used for image data, simulation outputs and time by region by product cubes, though for business analysis long-format data frames are usually easier to work with.
21

Tell me about a time you had two urgent analysis requests at the same time.

Save to ▾
Show answer
Situation: two managers needed different analyses on the same Friday. Task: deliver both without compromising quality. Action: I asked each what decision the analysis would support and the minimum needed by Friday, reused one cleaned dataset in R for both, and shared a draft of the simpler one on Wednesday for early feedback. Result: both received usable outputs on time, and the fuller version of the second analysis followed on Monday as agreed.
22

How do you apply the same transformation to many columns in dplyr?

Save to ▾
Show answer
across() applies one or more functions to a set of columns selected with tidyselect helpers. df %>% mutate(across(where(is.character), str_trim)) %>% mutate(across(starts_with('amt_'), ~ round(.x, 2))) df %>% group_by(region) %>% summarise(across(c(sales, profit), list(mean = mean, max = max), .names = '{.col}_{.fn}'))
23

How does a random forest work and which R packages implement it?

Save to ▾
Show answer
A random forest builds many decision trees, each on a bootstrap sample of rows and considering a random subset of features at each split, then averages their predictions for regression or takes a majority vote for classification. This reduces the variance of single trees and handles non-linear relationships well. In R, randomForest is the classic package and ranger is a much faster implementation. Key parameters are the number of trees, mtry and minimum node size.
24

You receive 60 monthly CSV files with the same structure. How do you combine them into one data frame?

Save to ▾
Show answer
I list the files with list.files(pattern = 'csv$', full.names = TRUE), then read them all at once with readr::read_csv(files, id = 'file'), which also records the source file. Alternatively I use purrr::map() with read_csv and dplyr::bind_rows(). Before combining, I check that column names and types match, because one file with text in a numeric column will fail or coerce the whole column. I then derive the month from the file name for traceability.
25

What are skewness and kurtosis?

Save to ▾
Show answer
Skewness measures asymmetry of a distribution. Positive or right skew has a long right tail, typical of income and order values, so the mean exceeds the median. Negative skew has a long left tail. Kurtosis measures how heavy the tails are compared with a normal distribution; high kurtosis means more extreme values, common in financial returns. In R, the moments or e1071 packages provide skewness() and kurtosis() functions.
26

You need month-over-month sales growth for each product. How do you calculate it in R?

Save to ▾
Show answer
I first aggregate to one row per product and month with group_by() and summarise(). Then I group by product, arrange by month and use mutate(growth = (sales - lag(sales)) / lag(sales) * 100). The first month for each product becomes NA, which is correct. I make sure months with zero sales exist using tidyr::complete(), otherwise lag() compares non-consecutive months. Finally I round and format growth for reporting.
27

What are closures and function factories in R?

Save to ▾
Show answer
A closure is a function that remembers the environment in which it was created. A function factory is a function that returns such functions. For example, power <- function(exp) function(x) x^exp; square <- power(2) creates a function that remembers exp = 2. They are useful for creating families of related functions, counters and memoised functions. Because of lazy evaluation, call force(exp) inside the factory so the value is captured immediately.
28

How do you produce descriptive statistics for each group in R?

Save to ▾
Show answer
Combine summary functions with dplyr, or use quick helpers for exploration. summary(df$salary) quantile(df$salary, c(0.1, 0.5, 0.9), na.rm = TRUE) df %>% group_by(department) %>% summarise(n = n(), mean = mean(salary, na.rm = TRUE), median = median(salary, na.rm = TRUE), sd = sd(salary, na.rm = TRUE), iqr = IQR(salary, na.rm = TRUE)) skimr::skim(df)
29

Your function gives correct results when you test it but wrong results in the main script. What could be the cause?

Save to ▾
Show answer
A common cause is that the function reads a variable from the global environment instead of taking it as an argument. During testing that global variable had one value, and in the main script it has another. Lexical scoping finds it silently. I would check the function body for names not defined as arguments or locally, for example using codetools::findGlobals(fn), and pass everything explicitly so the function is self-contained.
30

How do you build a logistic regression model for churn in R?

Save to ▾
Show answer
Use glm() with family = binomial; predictions with type = 'response' are probabilities. fit <- glm(churned ~ tenure + monthly_charges + contract, data = train, family = binomial) summary(fit) exp(coef(fit)) # odds ratios test$prob <- predict(fit, newdata = test, type = 'response') test$pred <- ifelse(test$prob > 0.5, 1, 0) table(actual = test$churned, predicted = test$pred)

Tips to crack the American Express R Programming interview

  • Learn credit card business basics like spend, revolve, delinquency and customer lifetime value for analytics interviews.
  • Practise SQL, Python and statistics, including model evaluation for risk or marketing use cases.
  • Read about American Express's Blue Box values and its strong focus on customer service.
  • Keep a one-minute story ready for every project on your CV: problem, your part, tools, result.
  • Practise the hard questions on this page aloud; American Express interviewers usually ask follow-ups on your first answer.

Frequently asked questions

How many rounds are there in the American Express R Programming interview?

Candidates usually go through 5 stages: Online assessment (aptitude + coding or analytics); Technical round; Case or domain round; Hiring manager round; HR round. The exact rounds change with the role, team, location and your experience, so confirm the process with the recruiter.

Which topics should I prepare for the American Express R Programming interview?

This practice set leans on Data Wrangling with dplyr and tidyr (5), Modelling and Machine Learning in R (5), Reports, Shiny and Production R (5), Data Structures in R (5). Revise those first, then practise explaining one or two of your own projects end to end, because most American Express interviewers ask you to walk through real work.

Are these the exact questions asked at American Express?

No. These are curated practice questions that match the skills and difficulty usually tested in banking & finance interviews like American Express's. They are not a leaked or verified list of past questions.

Where does American Express hire R Programming professionals in India?

American Express has large teams in Gurugram, Bengaluru. Openings and locations change often, so check the American Express careers page and filter by city and experience.

R Programming questions for similar companies