By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
A Hyper-Practical, Zero-Fluff Study Guide
You’re handed a dataset—maybe sales records, sensor logs, or customer behavior—and your boss says, "Tell me what’s going on in 10 minutes." Summary statistics, correlations, and covariance are your first line of defense against "data blindness." They let you: - Spot outliers (e.g., a single store skewing monthly revenue).- Detect relationships (e.g., "Does ad spend actually drive sales?").- Validate assumptions (e.g., "Are these two features redundant?").
Real-world scenario:You inherit a legacy ML pipeline predicting customer churn. The model’s accuracy is 92%, but the business says it’s useless. Why? The dataset has leaky features (e.g., "days_since_last_purchase" correlates too strongly with "churn" because it’s derived from the target). Summary stats would’ve caught this before deployment.
What breaks if you ignore this?- Garbage-in, garbage-out models (e.g., training on correlated features inflates accuracy).- Wasted compute (e.g., running expensive deep learning on data with no signal).- Wrong business decisions (e.g., "We’ll double ad spend!" based on a spurious correlation).
df.mean()
df.median()
df.std()
df.var()
df.min()
df.max()
df.quantile([0.25, 0.5, 0.75])
df.skew()
df.kurtosis()
df.cov()
df.corr()
pandas
numpy
seaborn
matplotlib
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # Load data df = pd.read_csv("titanic.csv") # Quick inspection print(df.head()) print("\nMissing values:\n", df.isnull().sum()) print("\nData types:\n", df.dtypes)
Expected output:
PassengerId Survived Pclass ... Fare Cabin Embarked 0 1 0 3 ... 7.2500 NaN S 1 2 1 1 ... 71.2833 C85 C 2 3 1 3 ... 7.9250 NaN S Missing values: PassengerId 0 Survived 0 Pclass 0 Name 0 Sex 0 Age 177 SibSp 0 Parch 0 Ticket 0 Fare 0 Cabin 687 Embarked 2 dtype: int64 Data types: PassengerId int64 Survived int64 Pclass int64 Name object Sex object Age float64 SibSp int64 Parch int64 Ticket object Fare float64 Cabin object Embarked object dtype: object
# Numeric columns only numeric_cols = df.select_dtypes(include=['int64', 'float64']).columns print(df[numeric_cols].describe()) # Skewness and kurtosis print("\nSkewness:\n", df[numeric_cols].skew()) print("\nKurtosis:\n", df[numeric_cols].kurtosis())
PassengerId Survived Pclass Age SibSp ... Parch Fare count 891.000000 891.000000 891.000000 714.000000 891.000000 ... 891.000000 891.000000 mean 446.000000 0.383838 2.308642 29.699118 0.523008 ... 0.381594 32.204208 std 257.353842 0.486592 0.836071 14.526497 1.102743 ... 0.806057 49.693429 min 1.000000 0.000000 1.000000 0.420000 0.000000 ... 0.000000 0.000000 25% 223.500000 0.000000 2.000000 20.125000 0.000000 ... 0.000000 7.910400 50% 446.000000 0.000000 3.000000 28.000000 0.000000 ... 0.000000 14.454200 75% 668.500000 1.000000 3.000000 38.000000 1.000000 ... 0.000000 31.000000 max 891.000000 1.000000 3.000000 80.000000 8.000000 ... 6.000000 512.329200 Skewness: PassengerId 0.0 Survived 0.5 Pclass 0.0 Age 0.4 SibSp 3.7 Parch 2.8 Fare 4.8 dtype: float64 Kurtosis: PassengerId -1.2 Survived -1.9 Pclass -1.5 Age -0.6 SibSp 14.3 Parch 8.6 Fare 25.0 dtype: float64
Key takeaways:- Fare is highly skewed (kurtosis = 25). Log transform may help.- Age has missing values (714/891 = 80% coverage).
Fare
Age
# Covariance matrix print("Covariance:\n", df[numeric_cols].cov()) # Correlation matrix (Pearson) print("\nCorrelation (Pearson):\n", df[numeric_cols].corr()) # Spearman correlation print("\nCorrelation (Spearman):\n", df[numeric_cols].corr(method='spearman'))
Expected output (Pearson):
PassengerId Survived Pclass Age SibSp Parch Fare PassengerId 6.623000e+04 -0.005007 -0.035144 0.036847 -0.057527 -0.001652 0.012658 Survived -5.007000e+00 0.235702 -0.338481 -0.077221 -0.035322 0.081629 0.257307 Pclass -3.514400e+01 -0.338481 0.699348 0.369226 0.083081 0.018443 -0.549500 Age 3.684700e+01 -0.077221 0.369226 210.997000 0.159651 0.081629 -0.096067 SibSp -5.752700e+00 -0.035322 0.083081 0.159651 1.216052 0.414838 0.159651 Parch -1.652000e+00 0.081629 0.018443 0.081629 0.414838 0.649715 0.216225 Fare 1.265800e+01 0.257307 -0.549500 -0.096067 0.159651 0.216225 2469.436846
Key takeaways:- Pclass and Fare are strongly negatively correlated (-0.55): Higher class = higher fare.- Survived correlates with Fare (0.26) and Pclass (-0.34): Richer passengers survived more.
Pclass
Survived
# Pairplot for numeric columns sns.pairplot(df[numeric_cols].dropna()) plt.show() # Heatmap of correlations sns.heatmap(df[numeric_cols].corr(), annot=True, cmap='coolwarm') plt.title("Correlation Heatmap") plt.show()
What to look for:- Linear trends (e.g., Pclass vs. Fare).- Outliers (e.g., a single passenger with Fare = 512).- Clusters (e.g., Age groups).
Fare = 512
df.fillna()
df.dropna()
python df['Age'].fillna(df['Age'].median(), inplace=True) # Robust to outliers
python assert (df['Age'] >= 0).all(), "Negative ages detected!"
.select_dtypes()
df.sample(10000)
sum(df[col])/len(df)
SibSp
Parch
sklearn.preprocessing.StandardScaler
python stats_report = df.describe().to_markdown() with open("stats_report.md", "w") as f: f.write(stats_report)
python outliers = df[df['Fare'] > 200] print("High-fare outliers:\n", outliers[['PassengerId', 'Fare', 'Pclass']])
NaN
sns.scatterplot
temperature
heater_usage
Answer: Strong negative linear relationship (higher temp → less heater use).
Method Selection: "Which correlation method should you use for ordinal data (e.g., survey responses 1-5)?"
Answer: Spearman (rank-based).
Outlier Impact: "A dataset has a mean of 50 and a median of 45. What does this suggest?"
Answer: Right-skewed data (outliers pulling mean up).
Covariance vs. Correlation: "Why is correlation preferred over covariance?"
Challenge: You’re given a dataset of house prices (price) and square footage (sqft). Compute the Pearson correlation between the two. Then, add a third column price_per_sqft = price / sqft and compute its correlation with sqft. What do you observe, and why?
price
sqft
price_per_sqft = price / sqft
Solution:
import pandas as pd # Sample data data = { 'price': [300000, 450000, 600000, 750000], 'sqft': [1500, 2000, 3000, 4000] } df = pd.DataFrame(data) df['price_per_sqft'] = df['price'] / df['sqft'] # Correlations print("Correlation (price vs. sqft):", df['price'].corr(df['sqft'])) print("Correlation (price_per_sqft vs. sqft):", df['price_per_sqft'].corr(df['sqft']))
Output:
Correlation (price vs. sqft): 1.0 Correlation (price_per_sqft vs. sqft): -1.0
Explanation: - price and sqft are perfectly correlated (1.0) because price_per_sqft is constant (e.g., $200/sqft).- price_per_sqft and sqft are perfectly negatively correlated (-1.0) because dividing by sqft inverts the relationship.
price_per_sqft
Why it matters: This is a mathematical artifact—not a real-world insight. Always check if derived features (like price_per_sqft) are introducing spurious correlations.
df.describe()
df.corr(method='spearman')
df.fillna(value)
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.