Medium Complexity
---
1. Find Consecutive Login Streaks for Users
You have a login dataset:
import pandas as pd
data = {
"user_id": [1, 1, 1, 2, 2, 2, 2],
"login_date": pd.to_datetime(["2024-03-01", "2024-03-02", "2024-03-04",
"2024-03-01", "2024-03-02", "2024-03-03", "2024-03-05"])
}
df = [Link](data)
print(df)
Question:
Find users who have logged in for at least 3 consecutive days.
Solution:
df["streak_group"] = df["login_date"] - pd.to_timedelta([Link]("user_id").cumcount(),
unit="D")
result = [Link](["user_id", "streak_group"])["login_date"].count().reset_index()
result = result[result["login_date"] >= 3][["user_id"]]
print(result)
✅ Concepts Tested: groupby(), cumcount(), timedelta, filtering
---
2. Find Employees Earning More Than Their Manager
You have an employee hierarchy dataset in a pandas DataFrame:
data = {
"id": [1, 2, 3, 4, 5],
"name": ["Alice", "Bob", "Carol", "Dave", "Eve"],
"salary": [8000, 5000, 9000, 6000, 7000],
"manager_id": [None, 1, 1, 2, 2]
}
df = [Link](data)
print(df)
Question:
Find employees who earn more than their direct manager.
Solution:
df_managers = [Link](columns={"id": "manager_id", "name": "manager_name", "salary":
"manager_salary"})
df_merged = [Link](df_managers, on="manager_id", how="left")
result = df_merged[df_merged["salary"] > df_merged["manager_salary"]][["name", "salary",
"manager_name", "manager_salary"]]
print(result)
✅ Concepts Tested: merge(), self-join, comparison filtering
---
3. Fill Missing Values Using the Mean of Each Group
You have a dataset with missing values:
data = {
"city": ["New York", "New York", "New York", "Los Angeles", "Los Angeles"],
"temperature": [25, None, 28, 30, None]
}
df = [Link](data)
print(df)
Question:
Fill missing values with the mean temperature of the respective city.
Solution:
df["temperature"] = df["temperature"].fillna([Link]("city")["temperature"].transform("mean"))
print(df)
✅ Concepts Tested: fillna(), groupby(), transform()
---
4. Find Users Who Purchased All Products
You have a purchase history dataset:
data = {
"user_id": [1, 1, 2, 2, 2, 3, 3],
"product": ["A", "B", "A", "B", "C", "A", "C"]
}
df = [Link](data)
print(df)
Question:
Find users who have purchased all available products.
Solution:
all_products = set(df["product"].unique())
result = [Link]("user_id")["product"].apply(set).reset_index()
result = result[result["product"] == all_products][["user_id"]]
print(result)
✅ Concepts Tested: groupby(), set operations, filtering
---
5. Compute a Rolling Average While Handling Missing Data
You have a time series dataset:
data = {
"date": pd.date_range(start="2024-03-01", periods=7),
"sales": [100, None, 200, 300, None, 500, 600]
}
df = [Link](data)
print(df)
Question:
Fill missing sales data using the previous available value (ffill), then compute a 3-day rolling
average.
Solution:
df["sales"] = df["sales"].fillna(method="ffill")
df["rolling_avg"] = df["sales"].rolling(3).mean()
print(df)
✅ Concepts Tested: fillna(), rolling(), forward fill
---
1. Detect and Remove Outliers Using the IQR Method
You have a dataset of product sales:
import pandas as pd
import numpy as np
data = {
"product": ["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"],
"sales": [100, 105, 110, 500, 115, 200, 220, 230, 1500, 240]
}
df = [Link](data)
print(df)
Question:
Find and remove outliers using the Interquartile Range (IQR) method.
Solution:
Q1 = [Link]("product")["sales"].transform(lambda x: [Link](0.25))
Q3 = [Link]("product")["sales"].transform(lambda x: [Link](0.75))
IQR = Q3 - Q1
df_cleaned = df[(df["sales"] >= (Q1 - 1.5 * IQR)) & (df["sales"] <= (Q3 + 1.5 * IQR))]
print(df_cleaned)
✅ Concepts Tested: groupby(), quantile(), IQR-based outlier removal
---
2. Find Consecutive Missing Values and Fill Using a Linear Trend
You have a time series dataset with missing values:
data = {
"date": pd.date_range(start="2024-03-01", periods=10),
"temperature": [20, [Link], [Link], 23, 24, [Link], 27, [Link], [Link], 30]
}
df = [Link](data)
print(df)
Question:
Fill consecutive missing values using linear interpolation.
Solution:
df["temperature"] = df["temperature"].interpolate(method="linear")
print(df)
✅ Concepts Tested: interpolate(), handling consecutive missing values
---
3. Remove Duplicate Rows Based on a Condition
You have a dataset with duplicate orders:
data = {
"order_id": [1, 2, 2, 3, 4, 4, 4, 5],
"customer": ["Alice", "Bob", "Bob", "Carol", "Dave", "Dave", "Dave", "Eve"],
"amount": [100, 200, 200, 150, 300, 300, 400, 500]
}
df = [Link](data)
print(df)
Question:
Keep only the row with the highest amount for each duplicate order_id.
Solution:
df_cleaned = df.sort_values(["order_id", "amount"], ascending=[True,
False]).drop_duplicates("order_id", keep="first")
print(df_cleaned)
✅ Concepts Tested: sort_values(), drop_duplicates(), condition-based deduplication
---
4. Create a Recursive Column to Track Running Totals Within Groups
You have a dataset of daily sales per store:
data = {
"store": ["X", "X", "X", "Y", "Y", "Y"],
"date": pd.date_range(start="2024-03-01", periods=6),
"sales": [100, 150, 200, 50, 75, 125]
}
df = [Link](data)
print(df)
Question:
Create a cumulative sum column that resets for each store.
Solution:
df["running_total"] = [Link]("store")["sales"].cumsum()
print(df)
✅ Concepts Tested: groupby(), cumsum(), recursive aggregation
---
5. Explode a Column with Multiple Values into Separate Rows
You have a dataset where each user has multiple purchased products in a single row:
data = {
"user_id": [1, 2, 3],
"products": ["A,B,C", "A,C", "B,C"]
}
df = [Link](data)
print(df)
Question:
Convert the products column into separate rows per user.
Solution:
df["products"] = df["products"].[Link](",")
df_exploded = [Link]("products")
print(df_exploded)
✅ Concepts Tested: [Link](), explode(), normalization of multi-value columns
---
Time series
---
1. Find Missing Time Intervals and Fill with Default Values
You have hourly sales data, but some hours are missing:
import pandas as pd
import numpy as np
data = {
"timestamp": pd.to_datetime([
"2024-03-01 08:00", "2024-03-01 09:00", "2024-03-01 11:00",
"2024-03-01 12:00", "2024-03-01 14:00"
]),
"sales": [10, 15, 20, 25, 30]
}
df = [Link](data)
print(df)
Question:
Find missing hours and fill them with zero sales.
Solution:
df = df.set_index("timestamp").resample("H").asfreq().fillna({"sales": 0})
print(df)
✅ Concepts Tested: resample(), asfreq(), filling missing time intervals
---
2. Compute a Rolling Weekly Sales Average
You have daily sales data, and you need to calculate a 7-day rolling average:
data = {
"date": pd.date_range(start="2024-03-01", periods=10),
"sales": [100, 120, 130, 140, 160, 180, 200, 210, 220, 250]
}
df = [Link](data)
print(df)
Question:
Compute a 7-day rolling average of sales.
Solution:
df["rolling_avg"] = df["sales"].rolling(7, min_periods=1).mean()
print(df)
✅ Concepts Tested: rolling(), mean(), smoothing time series data
---
3. Identify Daily Sales Growth Rate
You have daily sales data, and you want to track day-over-day percentage change:
data = {
"date": pd.date_range(start="2024-03-01", periods=7),
"sales": [100, 110, 90, 120, 150, 140, 160]
}
df = [Link](data)
print(df)
Question:
Compute the daily percentage change in sales.
Solution:
df["growth_rate"] = df["sales"].pct_change().mul(100).round(2)
print(df)
✅ Concepts Tested: pct_change(), multiplication, trend detection
---
4. Create Features for Time Series Forecasting
You have daily temperature data, and you need to create features for machine learning models.
data = {
"date": pd.date_range(start="2024-03-01", periods=10),
"temperature": [15, 16, 18, 19, 21, 23, 22, 20, 19, 17]
}
df = [Link](data)
print(df)
Question:
Create lagged temperature features for forecasting (yesterday's and two-day-ago
temperatures).
Solution:
df["temp_lag_1"] = df["temperature"].shift(1)
df["temp_lag_2"] = df["temperature"].shift(2)
print(df)
✅ Concepts Tested: shift(), feature engineering for forecasting
---
5. Decompose Time Series into Trend, Seasonality, and Residuals
You have monthly sales data and want to analyze its trend and seasonality.
from [Link] import seasonal_decompose
data = {
"date": pd.date_range(start="2023-01", periods=24, freq="M"),
"sales": [100, 120, 110, 130, 150, 170, 180, 160, 140, 130, 150, 170,
200, 220, 210, 230, 250, 270, 280, 260, 240, 230, 250, 270]
}
df = [Link](data).set_index("date")
print(df)
Question:
Perform seasonal decomposition to extract trend and seasonality.
Solution:
decomposition = seasonal_decompose(df["sales"], model="additive")
df["trend"] = [Link]
df["seasonal"] = [Link]
df["residual"] = [Link]
print(df)
✅ Concepts Tested: seasonal_decompose(), trend analysis & forecasting preparation
---
🚀 Full Time Series Forecasting Challenge
You are given daily energy consumption data and need to:
1️⃣ Handle missing values and outliers
2️⃣ Engineer features for forecasting
3️⃣ Detect anomalies
4️⃣ Build an ARIMA model for forecasting
---
🔹 Step 1: Generate Synthetic Energy Consumption Data
First, let's create a dataset with missing values and anomalies:
import pandas as pd
import numpy as np
# Generate date range
[Link](42)
dates = pd.date_range(start="2024-01-01", periods=100, freq="D")
# Generate normal energy consumption data
consumption = [Link](50, 100, size=len(dates)).astype(float)
# Introduce missing values
consumption[[5, 15, 30, 70]] = [Link]
# Introduce anomalies (sudden spikes)
consumption[50] = 500
consumption[80] = 10
df = [Link]({"date": dates, "energy_consumption": consumption})
print([Link](10))
---
🔹 Step 2: Fill Missing Values & Remove Outliers
We’ll use forward fill for missing values and remove anomalies using the IQR method.
Solution:
# Fill missing values with forward fill
df["energy_consumption"] = df["energy_consumption"].fillna(method="ffill")
# Detect outliers using IQR
Q1 = df["energy_consumption"].quantile(0.25)
Q3 = df["energy_consumption"].quantile(0.75)
IQR = Q3 - Q1
# Define upper and lower bounds
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# Remove outliers
df["energy_consumption"] = [Link](
(df["energy_consumption"] < lower_bound) | (df["energy_consumption"] > upper_bound),
[Link],
df["energy_consumption"]
)
# Fill anomalies with rolling mean
df["energy_consumption"] = df["energy_consumption"].fillna(df["energy_consumption"].rolling(3,
min_periods=1).mean())
print([Link](10))
✅ Concepts Tested: fillna(), IQR-based outlier detection, rolling mean for anomaly handling
---
🔹 Step 3: Feature Engineering for Forecasting
Now, let’s create lagged features and rolling statistics to improve forecasting accuracy.
Solution:
df["day_of_week"] = df["date"].[Link]
df["month"] = df["date"].[Link]
df["lag_1"] = df["energy_consumption"].shift(1)
df["lag_7"] = df["energy_consumption"].shift(7)
df["rolling_mean_7"] = df["energy_consumption"].rolling(7, min_periods=1).mean()
print([Link](10))
✅ Concepts Tested: shift(), rolling(), datetime features for forecasting
---
🔹 Step 4: Train an ARIMA Model for Forecasting
We’ll train an ARIMA model to forecast future energy consumption.
Solution:
from [Link] import ARIMA
# Set date as index
df.set_index("date", inplace=True)
# Fit ARIMA model
model = ARIMA(df["energy_consumption"], order=(2, 1, 2)) # ARIMA(p,d,q)
model_fit = [Link]()
# Forecast next 7 days
forecast = model_fit.forecast(steps=7)
forecast_dates = pd.date_range(start=[Link][-1] + [Link](days=1), periods=7)
forecast_df = [Link]({"date": forecast_dates, "forecasted_energy": forecast})
print(forecast_df)
✅ Concepts Tested: ARIMA modeling, time series forecasting, handling time series indices
---
🔹 Step 5: Visualize the Forecast
To evaluate the forecast, let’s plot actual vs. predicted values.
Solution:
import [Link] as plt
[Link](figsize=(10, 5))
[Link]([Link], df["energy_consumption"], label="Actual", color="blue")
[Link](forecast_df["date"], forecast_df["forecasted_energy"], label="Forecast", color="red",
linestyle="dashed")
[Link]("Date")
[Link]("Energy Consumption")
[Link]("Energy Consumption Forecast")
[Link]()
[Link]()
✅ Concepts Tested: matplotlib, visualizing forecasts, comparison of actual vs. predicted data
---
🔹 Final Output
✅ You successfully:
✔️ Cleaned missing values & outliers
✔️ Created lagged features for forecasting
✔️ Built an ARIMA model
✔️ Forecasted energy consumption
✔️ Visualized actual vs. predicted values
---
BASIC python Questions
---
1️⃣ What will this print?
def func(a, b=[]):
[Link](a)
return b
print(func(1))
print(func(2))
print(func(3, []))
print(func(4))
Answer:
[1]
[1, 2]
[3]
[1, 2, 4]
Explanation:
The default argument b=[] is mutable, so it retains changes across function calls.
func(1) modifies the default list b, so func(2) keeps the previous values.
func(3, []) creates a new list instead of modifying the shared default list.
✅ Concepts Tested: Mutable default arguments
---
2️⃣ Can you fix the infinite loop?
i=5
while i == 5:
print(i)
i += 1
Answer:
i=5
while i < 6: # Fixed condition
print(i)
i += 1
Explanation:
while i == 5 ensures the loop runs forever, because i will never be 5 again once incremented.
Changing it to while i < 6 allows it to exit.
✅ Concepts Tested: Loop conditions & logic errors
---
3️⃣ How does this lambda function behave?
funcs = [lambda x: x + n for n in range(5)]
print([f(0) for f in funcs])
Answer:
[4, 4, 4, 4, 4]
Explanation:
Late binding: The variable n is evaluated when the lambda is called, not when it is created.
By the time f(0) is executed, n = 4 for all lambda functions.
✅ Concepts Tested: Lambda & late binding in loops
---
4️⃣ Can you swap values without a third variable?
a, b = 5, 10
a, b = b, a
print(a, b) # Output: 10 5
Answer:
10 5
Explanation:
Python supports tuple unpacking, allowing swapping in a single line.
✅ Concepts Tested: Tuple unpacking, variable swapping
---
5️⃣ What will this return?
def extendList(val, list=[]):
[Link](val)
return list
list1 = extendList(10)
list2 = extendList(20, [])
list3 = extendList(30)
print(list1, list2, list3)
Answer:
[10, 30] [20] [10, 30]
Explanation:
The default list [] is shared across function calls.
extendList(10) and extendList(30) modify the same default list.
extendList(20, []) creates a new list, avoiding the issue.
✅ Concepts Tested: Mutable default arguments in functions
---
6️⃣ What’s wrong with this set operation?
set1 = {1, 2, 3}
set2 = {3, 4, 5}
print(set1 + set2)
Answer:
🚨 Error:
TypeError: unsupported operand type(s) for +: 'set' and 'set'
Fix: Use union() or | instead:
print(set1 | set2) # Output: {1, 2, 3, 4, 5}
✅ Concepts Tested: Set operations & invalid operators
---
7️⃣ What will this print?
def tricky(x, lst=[]):
[Link](x)
return lst
print(tricky(1))
print(tricky(2))
print(tricky(3, []))
print(tricky(4))
Answer:
[1]
[1, 2]
[3]
[1, 2, 4]
✅ Concepts Tested: Mutable default arguments in function definitions
---
8️⃣ What's wrong with this list comprehension?
nums = [1, 2, 3, 4]
squared = [x ** 2 for x in nums if x % 2 == 0 else x]
print(squared)
Answer:
🚨 Error:
SyntaxError: invalid syntax
Fix: Use if-else inside brackets:
squared = [x ** 2 if x % 2 == 0 else x for x in nums]
print(squared) # Output: [1, 4, 3, 16]
✅ Concepts Tested: List comprehensions & conditional expressions
---
9️⃣ What does this print?
def f(a, b, c=5, *args, **kwargs):
print(a, b, c, args, kwargs)
f(1, 2)
f(1, 2, 3, 4, 5, x=6, y=7)
Answer:
1 2 5 () {} # Default c=5, no extra args
1 2 3 (4, 5) {'x': 6, 'y': 7} # Extra positional & keyword args
✅ Concepts Tested: Function arguments (*args, **kwargs)
---
🔟 Can you spot the mistake?
class A:
def __init__(self):
self.x = 10
def show(self):
print(self.x)
a = A()
a.y = 20
print(a.y)
print(A().y) # What happens here?
Answer:
🚨 Error:
AttributeError: 'A' object has no attribute 'y'
Fix: Define y inside __init__():
class A:
def __init__(self):
self.x = 10
self.y = 20 # Now y is part of all instances
a = A()
print(a.y) # Works now!
✅ Concepts Tested: Instance attributes vs. dynamically assigned attributes
---
1️⃣ What will this print?
x = 0.1 + 0.2
print(x == 0.3)
Answer:
False
Explanation:
Due to floating-point precision errors, 0.1 + 0.2 is not exactly 0.3 but 0.30000000000000004.
To fix this, use round(x, 10) == round(0.3, 10).
✅ Concepts Tested: Floating-point precision
---
2️⃣ What will this print?
print(bool([]), bool({}), bool(()), bool(set()))
Answer:
False False False False
Explanation:
Empty collections (list, dict, tuple, set) evaluate to False in a boolean context.
✅ Concepts Tested: Falsy values in Python
---
3️⃣ What will this print?
x = "Hello"
y = "Hello"
print(x is y)
Answer:
True
Explanation:
String interning in Python means that short strings with only letters, numbers, and underscores
are stored at the same memory location for optimization.
Since "Hello" is a short string, x and y point to the same object in memory.
✅ Concepts Tested: String interning & memory management
---
4️⃣ What will this print?
a = [1, 2, 3]
b=a
[Link](4)
print(a)
Answer:
[1, 2, 3, 4]
Explanation:
b = a does not create a copy of a. Instead, b points to the same list object.
Changes made to b are reflected in a.
To create a separate copy, use b = [Link]() or b = a[:].
✅ Concepts Tested: Mutability & reference assignment
---
5️⃣ What will this print?
a = 10
b = 10
print(a is b)
Answer:
True
Explanation:
Python caches small integers (-5 to 256) in memory.
Since 10 falls within this range, a and b refer to the same object in memory.
✅ Concepts Tested: Integer caching
---
6️⃣ What will this print?
a = (1, 2, [3, 4])
a[2].append(5)
print(a)
Answer:
(1, 2, [3, 4, 5])
Explanation:
Tuples are immutable, but if they contain mutable objects (like lists), those elements can be
modified.
a[2] refers to a list, which allows append(5).
✅ Concepts Tested: Mutability inside immutable objects (tuples)
---
7️⃣ What’s the output of this loop?
for i in range(3):
print(i)
else:
print("Loop completed!")
Answer:
0
1
2
Loop completed!
Explanation:
The else block in a for loop executes only if the loop completes without a break statement.
Since there is no break, "Loop completed!" is printed.
✅ Concepts Tested: For-else behavior
---
8️⃣ What will this print?
print(2 ** 3 ** 2)
Answer:
512
Explanation:
Exponentiation (**) is right-associative in Python.
This means 3 ** 2 (which is 9) is evaluated first.
Then, 2 ** 9 = 512.
✅ Concepts Tested: Operator precedence in exponentiation
---
9️⃣ What will this print?
def func(val, lst=[]):
[Link](val)
return lst
print(func(1))
print(func(2))
print(func(3, []))
print(func(4))
Answer:
[1]
[1, 2]
[3]
[1, 2, 4]
Explanation:
The default argument lst=[] is mutable and persists across function calls.
func(1) modifies the same list used in func(2).
func(3, []) starts a new, separate list.
func(4) continues modifying the original default list.
✅ Concepts Tested: Mutable default arguments in functions
---
🔟 What will this print?
def my_func(x, y=[]):
[Link](x)
return y
print(my_func(5))
print(my_func(10))
Answer:
[5]
[5, 10]
Explanation:
The default list y=[] is shared across function calls.
my_func(5) appends 5 to the default list.
my_func(10) appends 10 to the same list, causing [5, 10].
To fix this issue, use:
def my_func(x, y=None):
if y is None:
y = []
[Link](x)
return y
✅ Concepts Tested: Mutable default arguments in functions
---