← Uber Interview Insights

Uber·Data Scientist·Take-home Assignment·Intermediate

Intermediate
May 2026

Summary

Uber data science take-home that looked straightforward on paper until you actually had to wire all the pandas steps together in the right order. Six tasks, two CSVs, a lot of edge cases baked in quietly.

Questions Asked (6)

Q1

Load two CSV files into DataFrames and verify the ingest by displaying the first two rows and last row of the trips data.

Product Analytics & Metrics
Author's notes

Basically a sanity check step, nothing tricky.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by importing pandas and reading both CSV files into DataFrames using pd.read_csv. Then use .head(2) to display the first two rows and .tail(1) to display the last row of the trips DataFrame, ensuring the output is clear and verifiable.

Pro tip: Mention that you would also check the shape and data types to ensure the data loaded correctly, and consider using a random sample or summary statistics for a more thorough validation.

1. Import pandas

Import the pandas library to access DataFrame functionality.

2. Load CSV files

Use pd.read_csv to load both CSV files into separate DataFrames, assigning them to variables like df1 and df2 or more descriptive names.

3. Display first two rows

Use the .head(2) method on the trips DataFrame to display the first two rows.

4. Display last row

Use the .tail(1) method on the trips DataFrame to display the last row.

5. Verify and explain

Explain that this quick check confirms the data loaded correctly and gives a sense of the structure and content.

Key Points to Mention

  • Use of pandas library for data manipulation
  • pd.read_csv for loading CSV files
  • head() and tail() methods for previewing data
  • Importance of verifying data ingestion
  • Potential need to check shape, columns, and data types
  • Handling of file paths and potential errors

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Drop rows with missing fare values or missing/empty route strings, and make sure the fare column is actually numeric after cleaning.

Data ModelingTechnical Trade-offs
Author's notes

The whitespace-stripping part is where I almost messed up.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by inspecting the data to understand the extent of missing values and the current data types, especially for fare and route columns. Then apply a cleaning pipeline that drops rows with missing fare or empty/whitespace route strings, and coerces the fare column to numeric, handling any conversion errors. Finally, validate the cleaned dataset to ensure no missing values remain and fare is numeric.

Pro tip: Always document the number of rows dropped and the reasons, as this demonstrates awareness of data loss impact and helps with reproducibility. Consider whether dropping missing fares could introduce bias, and mention alternative imputation strategies if appropriate.

1. Inspect and profile the data

Check the shape, data types, and missing value counts for fare and route columns. Identify empty strings or whitespace in route and non-numeric entries in fare.

2. Clean route column

Remove rows where route is missing, empty, or contains only whitespace. Optionally, strip whitespace and standardize route strings.

3. Clean fare column

Drop rows with missing fare values. Convert fare to numeric using pd.to_numeric with errors='coerce', then drop any rows that failed conversion (became NaN).

4. Validate and document

Verify that no missing fares or empty routes remain and that fare is numeric. Record the number of rows dropped and any assumptions made.

Key Points to Mention

  • Use of pandas functions: dropna, pd.to_numeric with errors='coerce', and string methods like str.strip() to handle empty/whitespace routes.
  • Importance of checking data types before and after cleaning to ensure fare is numeric (e.g., float or int).
  • Consideration of data loss: how many rows are dropped and whether this could bias the analysis.
  • Handling of edge cases: fare values with currency symbols or commas that need parsing before conversion.
  • Reproducibility: encapsulating cleaning steps in a function or pipeline for reuse.
  • Validation: using assertions or summary statistics to confirm cleaning success.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

Split the route column on the pipe character into separate origin and destination columns, trim whitespace from both, and drop rows where the split produces fewer than two parts.

Data ModelingAlgorithms & Data Structures
Author's notes

str.split with expand=True is clean but I forgot to set n=1 initially, which would've caused issues if any route had more than one pipe.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the data format and edge cases, then outline a step-by-step transformation using pandas: split the route column on the pipe, expand into two columns, trim whitespace, and filter out rows with fewer than two parts. Emphasize handling missing or malformed data and validating the result.

Pro tip: Mention that you would first inspect the distribution of split counts to understand data quality, and use vectorized string operations for efficiency rather than apply, which is slower on large datasets.

1. Understand the data and requirements

Inspect the route column to see typical values, delimiters, and potential edge cases like missing pipes or extra pipes. Clarify whether to keep only rows with exactly two parts or at least two parts.

2. Split the column

Use pandas' str.split method with the pipe delimiter and expand=True to create separate columns. This efficiently handles the split in a vectorized manner.

3. Trim whitespace

Apply str.strip to both resulting columns to remove leading and trailing whitespace, ensuring clean origin and destination values.

4. Filter invalid rows

Drop rows where the split did not produce at least two parts. This can be done by checking the number of non-null values in the split columns or by using a mask based on the original string containing the delimiter.

5. Validate and finalize

Check the resulting DataFrame for correct column names, data types, and no unexpected nulls. Optionally, rename columns to 'origin' and 'destination' and reset the index.

Key Points to Mention

  • Use of pandas str.split with expand=True for vectorized splitting
  • Handling of missing values or rows without the delimiter
  • Trimming whitespace with str.strip
  • Dropping rows with fewer than two parts using boolean indexing or dropna
  • Performance considerations for large datasets (avoid apply, use vectorized operations)
  • Validation of the output (e.g., checking value counts, ensuring no empty strings)

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

Merge the cleaned trips data with the drivers data on driver ID using a left join, then filter to keep only rows that matched a driver record.

Data ModelingTechnical Trade-offs
Author's notes

Left join then filter felt a bit redundant to me, like why not just do an inner join.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Walk through the join and filter logic step by step, explaining why a left join is used first and then why filtering to matched rows effectively converts it to an inner join. Emphasize the importance of validating the join keys and understanding the business context for why unmatched rows are dropped.

Pro tip: Mention that filtering after a left join to keep only matched rows is equivalent to an inner join, but the explicit left join + filter pattern can be useful for debugging or when you want to inspect unmatched rows before discarding them.

1. Understand the data and join keys

Verify that both datasets have a driver ID column, check for data types and potential duplicates, and understand the grain of each table.

2. Perform the left join

Use a left join to retain all trips and attach driver information where available, ensuring that trips without a matching driver get nulls for driver columns.

3. Filter to matched rows

Apply a filter to keep only rows where the driver ID from the drivers table is not null, effectively removing trips without a driver record.

4. Validate and explain the result

Check row counts and confirm that the output contains only trips with valid driver information, and discuss the equivalence to an inner join.

Key Points to Mention

  • Left join vs inner join semantics
  • Handling of unmatched rows (nulls)
  • Data quality checks (duplicates, null keys)
  • Performance considerations for large datasets
  • Business context for why unmatched trips are excluded
  • Potential need for further cleaning after join

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q5

Build a per-driver summary showing trip count, average fare rounded to two decimals, and the average fare across each driver's last three trips ordered by timestamp. If a driver has fewer than three trips, average over however many they have.

Product Analytics & MetricsAlgorithms & Data Structures
Author's notes

This was the part that took the most time.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the schema and edge cases, then outline a SQL solution using window functions to compute per-driver aggregates and a separate window to rank trips by timestamp. Combine the two using a join or conditional aggregation, ensuring correct rounding and handling of drivers with fewer than three trips.

Pro tip: Mention that you would validate the results by checking a few drivers manually and consider performance implications for large datasets, such as using appropriate indexes or partitioning.

1. Clarify requirements and schema

Ask about the table structure, column names, data types, and any constraints. Confirm definitions: trip count, average fare, and 'last three trips' based on timestamp.

2. Compute overall per-driver metrics

Use GROUP BY driver_id to calculate trip count and average fare, rounding to two decimals. Ensure handling of NULLs or invalid fares.

3. Identify last three trips per driver

Use a window function like ROW_NUMBER() OVER (PARTITION BY driver_id ORDER BY timestamp DESC) to rank trips, then filter for rank <= 3.

4. Compute average fare over last three trips

For each driver, calculate the average fare of the selected last three trips (or fewer if not available), rounding to two decimals.

5. Combine and present results

Join the overall metrics with the last-three-trip average, ensuring all drivers are included. Output driver_id, trip_count, avg_fare, and avg_last_3_fare.

Key Points to Mention

  • Use of window functions (ROW_NUMBER, RANK) to identify last three trips per driver.
  • Handling drivers with fewer than three trips by averaging over available trips.
  • Rounding averages to two decimal places using ROUND().
  • Potential need for a subquery or CTE to combine overall and last-three averages.
  • Consideration of ties in timestamps and how to break them (e.g., by trip_id).
  • Performance considerations for large datasets, such as indexing on driver_id and timestamp.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q6

Return the top two drivers ranked by average fare descending, with ties broken by trip count descending and then driver name ascending. Also print the final DataFrame's column types.

Product Analytics & MetricsData Modeling
Author's notes

sort_values with multiple columns and mixed ascending/descending is one of those things I always have to look up.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the data schema and assumptions (e.g., whether 'fare' is per trip or total, and how to handle missing values). Then outline the aggregation and sorting logic: group by driver, compute average fare and trip count, sort by average fare descending, trip count descending, and driver name ascending, and take the top two. Finally, mention how to inspect the resulting DataFrame's column types, such as using df.dtypes or df.info().

Pro tip: Explicitly state that you would validate the result by checking for ties at the cutoff and confirming that the sorting order matches the business requirement, since ranking logic is a common source of subtle bugs.

1. Clarify data and assumptions

Ask about the data schema, what 'fare' represents, and how to handle missing or invalid values. Confirm that 'driver' is a unique identifier and that 'trip count' means the number of trips per driver.

2. Aggregate metrics per driver

Group the data by driver and compute the average fare and the number of trips for each driver. Ensure that the average is calculated correctly (e.g., mean of fare column).

3. Sort and rank drivers

Sort the aggregated DataFrame by average fare descending, then by trip count descending, then by driver name ascending. Use a stable sort or specify all keys to ensure correct tie-breaking.

4. Select top two drivers

Take the first two rows after sorting to get the top two drivers. Optionally, reset the index or keep driver as a column for clarity.

5. Inspect column types

Print the DataFrame's column types using df.dtypes or df.info() to show the data types of each column in the final result.

Key Points to Mention

  • Grouping by driver and computing average fare and trip count
  • Multi-level sorting with descending and ascending orders
  • Handling ties correctly by specifying all sort keys
  • Using df.dtypes or df.info() to check column types
  • Considering data quality issues like missing fares or driver IDs
  • Validating the result by checking for ties at the cutoff

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.