Difficulty: Intermediate
Choosing the right chart type is one of the most important decisions in data visualization. Each chart type is designed to communicate a specific kind of relationship in your data, and using the wrong one can mislead viewers or obscure insights. A bar chart excels at comparing discrete categories, a line chart shows trends over time, a scatter plot reveals relationships between two continuous variables, a histogram displays the distribution of a single variable, a pie chart shows parts of a whole, and a box plot summarizes the spread and outliers of a distribution. Knowing when to use each type is a fundamental data literacy skill.
Bar charts are among the most versatile and widely used chart types. A vertical bar chart (plt.bar) is ideal for comparing values across categories, such as sales by product or scores by student. A horizontal bar chart (plt.barh) works better when category labels are long. Grouped bar charts place multiple bars side by side for each category to compare sub-groups, while stacked bar charts stack bars on top of each other to show both individual and total values. The key principle is that the length or height of each bar should be proportional to the value it represents, always starting from a zero baseline to avoid misleading comparisons.
Scatter plots are the go-to chart for exploring the relationship between two continuous variables. Each data point is represented as a dot at the (x, y) position determined by its two variable values. Patterns in scatter plots reveal correlations: a upward-sloping cloud of points suggests a positive correlation, a downward slope suggests a negative correlation, and a random scatter suggests no linear relationship. You can add a third dimension by varying the dot size (bubble chart) or color to encode additional variables. Scatter plots are invaluable in exploratory data analysis and are frequently used to check assumptions before building regression models.
Histograms and box plots both describe distributions but in different ways. A histogram divides the range of a continuous variable into bins and counts how many values fall in each bin, showing the shape of the distribution -- whether it is symmetric, skewed, bimodal, or uniform. The number of bins significantly affects the appearance: too few bins obscure patterns, too many create noise. Box plots (also called box-and-whisker plots) provide a compact summary showing the median, first and third quartiles (the box), and whiskers extending to 1.5 times the interquartile range. Points beyond the whiskers are plotted individually as outliers. Box plots are especially useful for comparing distributions across multiple groups side by side.
Pie charts show the proportional composition of a whole. Each slice represents a category's share of the total, with the angle proportional to its percentage. While pie charts are intuitive for showing simple proportions (like market share), they are often criticized by data visualization experts because humans are poor at comparing angles and areas. If you have more than five or six categories, a horizontal bar chart sorted by value is almost always more readable. Donut charts, a variation with a hollow center, are sometimes used to reduce the emphasis on area comparison. In interviews, knowing the limitations of pie charts and being able to suggest alternatives demonstrates strong data visualization judgment.
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
categories = ['Python', 'JavaScript', 'Java', 'C++', 'Go']
users = [35, 28, 22, 15, 10]
fig, ax = plt.subplots()
bars = ax.bar(categories, users, color=['#3776ab', '#f7df1e', '#b07219', '#00599C', '#00ADD8'])
ax.set_title('Language Popularity Survey')
ax.set_ylabel('Respondents (%)')
# Analyze the data
total = sum(users)
print("Bar chart data:")
for cat, val in zip(categories, users):
pct = val / total * 100
print(f" {cat}: {val} ({pct:.1f}%)")
print(f"Total respondents: {total}")
print(f"Most popular: {categories[users.index(max(users))]}")
plt.close(fig)
A bar chart maps categories to bar heights. We assign a custom color to each bar to match common language branding. The analysis computes each category's percentage of the total, which is exactly what a bar chart visually communicates.
# Compute correlation without needing to render a scatter plot
hours_studied = [2, 3, 5, 6, 7, 8, 9, 10, 4, 6]
exam_scores = [55, 60, 72, 75, 80, 85, 90, 95, 65, 78]
n = len(hours_studied)
mean_x = sum(hours_studied) / n
mean_y = sum(exam_scores) / n
numerator = sum((x - mean_x) * (y - mean_y) for x, y in zip(hours_studied, exam_scores))
denominator_x = sum((x - mean_x) ** 2 for x in hours_studied) ** 0.5
denominator_y = sum((y - mean_y) ** 2 for y in exam_scores) ** 0.5
correlation = numerator / (denominator_x * denominator_y)
print(f"Scatter plot: Hours Studied vs Exam Score")
print(f"Data points: {n}")
print(f"X range: {min(hours_studied)} - {max(hours_studied)} hours")
print(f"Y range: {min(exam_scores)} - {max(exam_scores)} points")
print(f"Correlation (r): {correlation:.4f}")
if correlation > 0.7:
print("Pattern: Strong positive correlation")
elif correlation > 0.3:
print("Pattern: Moderate positive correlation")
else:
print("Pattern: Weak or no correlation")
For a scatter plot, the key analysis is correlation. We compute Pearson's r manually: a value close to 1 indicates a strong positive linear relationship. This tells us the scatter plot would show points tightly clustered along an upward-sloping line.
# Simulate histogram computation
scores = [45, 52, 58, 60, 62, 65, 67, 68, 70, 72, 73, 75, 76, 78, 80, 82, 84, 85, 88, 90, 92, 95]
# Create bins manually
bin_edges = [40, 50, 60, 70, 80, 90, 100]
bins = {f"{bin_edges[i]}-{bin_edges[i+1]}": 0 for i in range(len(bin_edges)-1)}
for score in scores:
for i in range(len(bin_edges)-1):
if bin_edges[i] <= score < bin_edges[i+1]:
key = f"{bin_edges[i]}-{bin_edges[i+1]}"
bins[key] += 1
break
else:
key = f"{bin_edges[-2]}-{bin_edges[-1]}"
bins[key] += 1
print("Histogram: Exam Score Distribution")
print(f"Total values: {len(scores)}")
print(f"Bins: {len(bin_edges)-1}")
print("---")
for bin_range, count in bins.items():
bar = '#' * count
print(f" {bin_range}: {bar} ({count})")
print(f"---")
print(f"Mean: {sum(scores)/len(scores):.1f}")
sorted_scores = sorted(scores)
mid = len(sorted_scores) // 2
median = (sorted_scores[mid-1] + sorted_scores[mid]) / 2 if len(sorted_scores) % 2 == 0 else sorted_scores[mid]
print(f"Median: {median}")
A histogram divides continuous data into bins and counts values in each. The text-based bar visualization shows the distribution shape: here we see a roughly bell-shaped distribution centered around 70-80, which is what the histogram would visualize graphically.
def box_plot_stats(data, label):
s = sorted(data)
n = len(s)
median = (s[n//2 - 1] + s[n//2]) / 2 if n % 2 == 0 else s[n//2]
lower = s[:n//2]
upper = s[n//2 + (n % 2):]
q1 = (lower[len(lower)//2 - 1] + lower[len(lower)//2]) / 2 if len(lower) % 2 == 0 else lower[len(lower)//2]
q3 = (upper[len(upper)//2 - 1] + upper[len(upper)//2]) / 2 if len(upper) % 2 == 0 else upper[len(upper)//2]
iqr = q3 - q1
lower_fence = q1 - 1.5 * iqr
upper_fence = q3 + 1.5 * iqr
outliers = [x for x in s if x < lower_fence or x > upper_fence]
print(f"{label}:")
print(f" Min: {s[0]}, Q1: {q1}, Median: {median}, Q3: {q3}, Max: {s[-1]}")
print(f" IQR: {iqr}, Fences: [{lower_fence:.1f}, {upper_fence:.1f}]")
print(f" Outliers: {outliers if outliers else 'None'}")
team_a = [45, 50, 55, 58, 60, 62, 65, 68, 70, 95]
team_b = [55, 60, 62, 65, 67, 70, 72, 75, 78, 80]
print("Box Plot Comparison:")
box_plot_stats(team_a, "Team A")
box_plot_stats(team_b, "Team B")
A box plot shows five-number summary statistics. Team A has an outlier at 95 (above the upper fence of 87.5), while Team B's data is entirely within its fences. The median line, box (Q1-Q3), and whiskers give a compact view of each distribution's center and spread.
bar charts, scatter plots, histograms, pie charts, box plots