Why Visualise Data? 👀Data को Visualise क्यों करें? 👀为什么要可视化数据?👀
Numbers alone rarely tell the full story. A table of ten thousand rows can hide a straight-line trend, a cluster of odd values, or a seasonal spike. You do not see them until you plot. A chart turns numbers into shape, colour and position — things the eye reads very fast.
सिर्फ़ संख्याएँ पूरी कहानी कम ही बताती हैं। दस हज़ार rows की table में सीधी-रेखा वाला trend, अजीब मानों का झुंड, या मौसमी उछाल छिपा हो सकता है। Plot करने से पहले वे दिखते नहीं। Chart संख्याओं को आकार, रंग और जगह में बदल देता है — ऐसी चीज़ें जिन्हें आँख बहुत तेज़ी से पढ़ती है।
光看数字很少能讲清全部故事。一张一万行的表格里,可能藏着一条直线趋势、一簇异常值或一次季节性高峰 —— 不画图就看不见。图表把数字变成形状、颜色和位置,而这些正是眼睛读得最快的东西。
In 1973 the statistician Francis Anscombe built four small datasets (11 points each) with the same mean, variance, correlation and best-fit line. Plotted, they look nothing alike. It is a strong reminder that summary statistics alone can hide what is really going on.
1973 में statistician Francis Anscombe ने चार छोटे datasets (हर एक में 11 points) बनाए, जिनका mean, variance, correlation और best-fit line एक जैसे थे। Plot करने पर वे बिल्कुल अलग दिखते हैं। यह याद दिलाता है कि सिर्फ़ summary statistics असली बात छिपा सकते हैं।
1973 年,统计学家弗朗西斯·安斯库姆构造了四个小数据集(各 11 个点),它们的均值、方差、相关系数和最佳拟合直线都相同。画出来却完全不一样。它有力地提醒我们:只看汇总统计量可能会掩盖真实情况。
Note: "variance ≈ 11" is the variance of x. The variance of y is about 4.12. Each panel is a separate dataset — do not put all four on one chart.
ध्यान दें: "variance ≈ 11" x का variance है। y का variance लगभग 4.12 है। हर panel अलग dataset है — चारों को एक chart पर न डालें।
注意:“方差 ≈ 11”指的是 x 的方差,y 的方差约为 4.12。每个面板是一个独立数据集 —— 不要把四组画在同一张图上。
# 1) Anscombe's quartet: the numbers agree, the pictures do not
import numpy as np
x = [10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5]
ys = {"I": [8.04, 6.95, 7.58, 8.81, 8.33, 9.96, 7.24, 4.26, 10.84, 4.82, 5.68],
"II": [9.14, 8.14, 8.74, 8.77, 9.26, 8.10, 6.13, 3.10, 9.13, 7.26, 4.74],
"III": [7.46, 6.77, 12.74, 7.11, 7.81, 8.84, 6.08, 5.39, 8.15, 6.42, 5.73],
"IV": [6.58, 5.76, 7.71, 8.84, 8.47, 7.04, 5.25, 12.50, 5.56, 7.91, 6.89]}
x4 = [8, 8, 8, 8, 8, 8, 8, 19, 8, 8, 8]
for k, y in ys.items():
xx = np.array(x4 if k == "IV" else x); y = np.array(y)
slope, icpt = np.polyfit(xx, y, 1)
print(f"{k:>3}: mean x {xx.mean():.2f} var x {xx.var(ddof=1):.2f} mean y {y.mean():.2f} "
f"var y {y.var(ddof=1):.2f} r {np.corrcoef(xx, y)[0, 1]:.3f} line y = {icpt:.2f} + {slope:.3f}x")
In 2017, Justin Matejka and George Fitzmaurice took the idea further with the "Datasaurus Dozen": they moved points step by step, keeping the statistics fixed to 2 decimals, until the cloud turned into a dinosaur, a star or a circle. The simulator below does the same thing live.
2017 में Justin Matejka और George Fitzmaurice ने यह विचार "Datasaurus Dozen" से आगे बढ़ाया: उन्होंने points को क़दम-दर-क़दम खिसकाया, statistics को 2 दशमलव तक स्थिर रखते हुए, जब तक बादल dinosaur, तारा या वृत्त नहीं बन गया। नीचे का simulator यही काम live करता है।
2017 年,Justin Matejka 和 George Fitzmaurice 用“Datasaurus Dozen”把这个思想推进了一步:他们一步步移动数据点,同时把统计量固定在 2 位小数,直到点云变成恐龙、星形或圆。下面的模拟器现场演示同样的过程。
100 points. Each tiny move is accepted only if all five statistics stay the same to 2 decimals. Pick a target shape and watch.
100 points। हर छोटी चाल तभी मानी जाती है जब पाँचों statistics 2 दशमलव तक वही रहें। एक लक्ष्य आकार चुनें और देखें।
100 个点。每一次微小移动,只有五个统计量在 2 位小数内都不变时才会被接受。选一个目标形状,然后观察。
Choosing the Right Chart 🧭सही Chart चुनना 🧭选择合适的图表 🧭
Every chart type answers a certain kind of question. Start from the question, not from what looks nice.
हर chart type एक ख़ास तरह के सवाल का जवाब देता है। सवाल से शुरू करें, सुंदर दिखने से नहीं।
每种图表都回答某一类问题。从问题出发,而不是从好不好看出发。
| Question you are askingआपका सवाल你要问的问题 | Chart typeChart type图表类型 | seaborn / plotlyseaborn / plotlyseaborn / plotly |
|---|---|---|
| What is the shape of one numeric variable?एक numeric variable का आकार कैसा है?一个数值变量的分布形状如何? | Histogram, KDE, violinHistogram, KDE, violin直方图、KDE、小提琴图 | histplot, kdeplot, violinplot |
| How do two numeric variables relate?दो numeric variables कैसे जुड़े हैं?两个数值变量有什么关系? | Scatter, joint plotScatter, joint plot散点图、联合分布图 | scatterplot, jointplot, px.scatter |
| How does a value change over time?समय के साथ मान कैसे बदलता है?数值如何随时间变化? | Line chartLine chart折线图 | lineplot, px.line |
| How do categories compare?Categories की तुलना कैसी है?各类别如何比较? | Bar chart (sorted)Bar chart (sorted)条形图(排序) | barplot, countplot |
| Correlations among many variables?कई variables के बीच correlations?多个变量之间的相关? | Heatmap, pair plotHeatmap, pair plot热力图、配对图 | heatmap, pairplot |
| Spread and outliers by group?Group के हिसाब से फैलाव और outliers?按组看离散和异常值? | Box plot, strip plotBox plot, strip plot箱线图、带状散点图 | boxplot, stripplot |
| Parts of a whole (2–3 parts)?पूरे के हिस्से (2–3 हिस्से)?整体中的组成(2–3 部分)? | Stacked bar; a pie is fine for very few partsStacked bar; बहुत कम हिस्सों के लिए pie ठीक है堆叠条形图;部分很少时饼图也可以 | px.pie, px.bar |
Experiments by Cleveland and McGill (1984) found that people judge position and length more accurately than angle or area. So a bar chart is usually easier to read when you compare many similar parts. A pie can still work for 2–3 parts that clearly differ, like "70% / 30%". Try the "Pie vs bar" mode in Section 8.
Cleveland और McGill (1984) के प्रयोगों में पाया गया कि लोग जगह और लंबाई को कोण या क्षेत्रफल से ज़्यादा सटीक आँकते हैं। इसलिए कई मिलते-जुलते हिस्सों की तुलना में bar chart आम तौर पर पढ़ना आसान है। 2–3 साफ़ अलग हिस्सों, जैसे "70% / 30%", के लिए pie फिर भी चल सकता है। Section 8 में "Pie बनाम bar" mode आज़माएँ।
Cleveland 和 McGill(1984)的实验发现,人们对位置和长度的判断比对角度或面积更准确。因此比较许多相近的部分时,条形图通常更易读。对于 2–3 个差别明显的部分(如“70% / 30%”),饼图仍然可用。可以在第 8 节试试“饼图 vs 条形图”模式。
Distribution Plots — Understanding Shape 📊Distribution Plots — आकार समझना 📊分布图 —— 理解形状 📊
Before any model, look at how each numeric variable is spread out. Distribution plots show the centre, the spread, the skew and the odd values at a glance. All pictures in this tutorial come from two practice datasets made in Section 9: customers.csv (2,000 customers) and daily_sales.csv (2 years of daily revenue).
किसी भी model से पहले देखें कि हर numeric variable कैसे फैला है। Distribution plots एक नज़र में केंद्र, फैलाव, skew और अजीब मान दिखाते हैं। इस tutorial की सभी तस्वीरें Section 9 में बने दो practice datasets से हैं: customers.csv (2,000 ग्राहक) और daily_sales.csv (2 साल की रोज़ की revenue)।
建模之前,先看每个数值变量是如何分布的。分布图能一眼看出中心、离散程度、偏态和异常值。本教程所有图都来自第 9 节生成的两个练习数据集:customers.csv(2,000 位顾客)和 daily_sales.csv(两年的每日收入)。
Histogram with KDEKDE के साथ Histogram直方图与 KDE
A histogram cuts the range into bins and counts the values in each bin. A KDE (kernel density estimate) puts a small smooth bump on every value and adds them up, giving a smooth curve. Both depend on a setting you choose: the number of bins, and the KDE bandwidth.
Histogram range को bins में काटता है और हर bin के मान गिनता है। KDE (kernel density estimate) हर मान पर एक छोटा चिकना उभार रखता है और उन्हें जोड़ देता है, जिससे चिकना curve बनता है। दोनों आपकी चुनी setting पर निर्भर हैं: bins की संख्या, और KDE bandwidth।
直方图把取值范围切成若干区间(bin),统计每个区间里的值。KDE(核密度估计)在每个值上放一个小的平滑“鼓包”,再把它们加起来,得到一条平滑曲线。两者都取决于你选的设置:分组数和 KDE 带宽。
Right-skewed: a few large purchases form a long tail on the right and pull the mean above the median. For skewed money columns, report the median, or plot on a log scale.
Right-skewed: कुछ बड़ी ख़रीदें दाईं ओर लंबी tail बनाती हैं और mean को median से ऊपर खींचती हैं। Skewed पैसे वाले columns के लिए median बताएँ, या log scale पर plot करें।
右偏:少数大额消费在右侧形成长尾,把均值拉到中位数之上。对于偏态的金额列,应报告中位数,或用对数刻度作图。
400 values. Move the sliders: with too few bins the two delivery groups merge into one hump; with too many, noise looks like real peaks.
400 मान। Sliders खिसकाएँ: बहुत कम bins में दोनों delivery groups एक उभार बन जाते हैं; बहुत ज़्यादा में शोर असली चोटियों जैसा दिखता है।
400 个值。拖动滑块:分组太少时,两组配送时间会合并成一个峰;分组太多时,噪声看起来像真实的峰。
Box Plot — Spread and OutliersBox Plot — फैलाव और Outliers箱线图 —— 离散与异常值
Electronics and Furniture have the highest medians and the widest boxes. Many red dots above each box show a long right tail: on skewed money data, most "outliers" are real big orders, not errors.
Electronics और Furniture के median सबसे ऊँचे और box सबसे चौड़े हैं। हर box के ऊपर कई लाल बिंदु लंबी right tail दिखाते हैं: skewed पैसे वाले data में ज़्यादातर "outliers" असली बड़े orders हैं, ग़लतियाँ नहीं।
Electronics 和 Furniture 的中位数最高、箱体最宽。每个箱体上方的许多红点显示出右侧长尾:在偏态的金额数据中,大多数“异常值”是真实的大订单,而不是错误。
# 2) Distributions: histogram + KDE, box plots by category
import pandas as pd, seaborn as sns, matplotlib
matplotlib.use("Agg"); import matplotlib.pyplot as plt
df = pd.read_csv("customers.csv")
fig, ax = plt.subplots(1, 2, figsize=(11, 4))
sns.histplot(df["purchase_amount"], bins=40, kde=True, ax=ax[0])
sns.boxplot(data=df, x="product_category", y="purchase_amount",
hue="product_category", legend=False, ax=ax[1]) # seaborn 0.13: give hue when you set colours
fig.savefig("dist.png", dpi=80)
s = df["purchase_amount"]
print(f"mean {s.mean():,.0f} median {s.median():,.0f} skew {s.skew():.2f}")
print(df.groupby("product_category")["purchase_amount"].quantile([.25, .5, .75]).unstack().round(-1))
Writing sns.boxplot(..., palette="muted") without hue now gives a FutureWarning. Pass the same column to hue and set legend=False, as in the code above. To show every raw point on top of a box, add sns.stripplot(..., jitter=True, alpha=0.4, size=3).
hue के बिना sns.boxplot(..., palette="muted") लिखने पर अब FutureWarning आती है। वही column hue में दें और legend=False रखें, जैसा ऊपर के code में है। Box के ऊपर हर असली point दिखाने के लिए sns.stripplot(..., jitter=True, alpha=0.4, size=3) जोड़ें।
不带 hue 写 sns.boxplot(..., palette="muted") 现在会触发 FutureWarning。像上面的代码那样,把同一列传给 hue 并设置 legend=False。若想在箱体上叠加每个原始点,可加 sns.stripplot(..., jitter=True, alpha=0.4, size=3)。
Relationship Plots — Finding Connections 🔗Relationship Plots — संबंध खोजना 🔗关系图 —— 寻找关联 🔗
Relationship plots show how two or more variables move together. They help you pick useful features — but a link you see is a clue, not proof that one thing causes the other.
Relationship plots दिखाते हैं कि दो या ज़्यादा variables साथ-साथ कैसे चलते हैं। ये काम के features चुनने में मदद करते हैं — पर दिखा हुआ संबंध एक सुराग है, यह सबूत नहीं कि एक चीज़ दूसरी की वजह है।
关系图展示两个或多个变量如何一起变化。它们能帮你挑选有用的特征 —— 但看到的关联只是线索,不能证明一件事导致了另一件事。
Scatter Plot with Colour for GroupsGroups के लिए रंग वाला Scatter Plot用颜色区分组的散点图
900 of 2,000 customers shown. Older customers are more often in higher income brackets (more amber and red to the right), and higher brackets spend a bit more. But the colours overlap a lot: product category drives spend much more than age or income here.
2,000 में से 900 ग्राहक दिखाए गए हैं। बड़ी उम्र के ग्राहक ज़्यादा बार ऊँचे income brackets में हैं (दाईं ओर ज़्यादा amber और लाल), और ऊँचे brackets थोड़ा ज़्यादा ख़र्च करते हैं। पर रंग बहुत मिले हुए हैं: यहाँ ख़र्च को उम्र या income से कहीं ज़्यादा product category तय करती है।
图中显示 2,000 位顾客中的 900 位。年龄越大的顾客越常处于较高收入档(右侧琥珀色和红色更多),高收入档的消费也略高。但颜色重叠很多:在这里,决定消费的主要是商品类别,而不是年龄或收入。
Correlation HeatmapCorrelation Heatmap相关热力图
A heatmap of the correlation matrix shows every pairwise Pearson correlation as a coloured cell. Hide the upper half with a mask — it only repeats the lower half.
Correlation matrix का heatmap हर जोड़ी का Pearson correlation एक रंगीन cell के रूप में दिखाता है। ऊपरी आधा mask से छिपाएँ — वह सिर्फ़ निचले आधे को दोहराता है।
相关矩阵热力图把每一对变量的 Pearson 相关系数显示为一个彩色格子。用 mask 隐藏上半部分 —— 它只是下半部分的重复。
Strongest links: age–income 0.68 and delivery–rating −0.71 (slower delivery, lower rating). Income–purchase is only 0.31. Values near 0 mean "no straight-line link" — not always "no link at all".
सबसे मज़बूत संबंध: age–income 0.68 और delivery–rating −0.71 (धीमी delivery, कम rating)। Income–purchase सिर्फ़ 0.31 है। 0 के पास के मान का मतलब "कोई सीधी-रेखा संबंध नहीं" — हमेशा "कोई संबंध नहीं" नहीं।
最强的关联:age–income 0.68,delivery–rating −0.71(配送越慢,评分越低)。income–purchase 只有 0.31。接近 0 的值表示“没有直线关系”,并不总是“完全没有关系”。
# 3) Relationships: scatter with colour, and a correlation heatmap
import numpy as np, pandas as pd, seaborn as sns, matplotlib
matplotlib.use("Agg"); import matplotlib.pyplot as plt
df = pd.read_csv("customers.csv")
sns.scatterplot(data=df, x="age", y="purchase_amount", hue="income_bracket",
hue_order=["Low", "Medium", "High", "Very High"], alpha=0.6)
plt.yscale("log"); plt.savefig("scatter.png", dpi=80); plt.close()
corr = df.select_dtypes("number").corr().round(2)
mask = np.triu(np.ones_like(corr, dtype=bool)) # hide the repeated upper half
sns.heatmap(corr, mask=mask, annot=True, fmt=".2f", cmap="coolwarm", center=0, vmin=-1, vmax=1)
plt.savefig("heatmap.png", dpi=80)
print(corr)
Set a target r, then switch patterns. Watch the heatmap cell on the right: it can look the same for very different pictures.
एक लक्ष्य r चुनें, फिर patterns बदलें। दाईं ओर heatmap cell देखें: बहुत अलग तस्वीरों के लिए वह एक जैसा दिख सकता है।
设定目标 r,然后切换模式。注意右边的热力图格子:完全不同的图形,它可能看起来一样。
(1) Pearson r only measures straight-line links; use Spearman (df.corr(method="spearman")) for ranked or curved-but-steady links. (2) One outlier can create or hide a correlation, so check the scatter plot. (3) Correlation is not causation. (4) A common rule of thumb is to look closer when two features correlate above about 0.8–0.9 (multicollinearity). It is a heuristic; the variance inflation factor (VIF) is a better check for regression.
(1) Pearson r सिर्फ़ सीधी-रेखा संबंध मापता है; ranked या मुड़े-पर-एक-दिशा वाले संबंधों के लिए Spearman (df.corr(method="spearman")) इस्तेमाल करें। (2) एक outlier correlation बना या छिपा सकता है, इसलिए scatter plot देखें। (3) Correlation, causation नहीं है। (4) आम rule of thumb है कि दो features का correlation लगभग 0.8–0.9 से ऊपर हो तो क़रीब से देखें (multicollinearity)। यह एक अनुमानित नियम है; regression के लिए variance inflation factor (VIF) बेहतर जाँच है।
(1) Pearson r 只衡量直线关系;对于排序型或弯曲但单调的关系,用 Spearman(df.corr(method="spearman"))。(2) 一个异常点就能制造或掩盖相关,所以要看散点图。(3) 相关不等于因果。(4) 常见经验是:两个特征相关超过约 0.8–0.9 时要仔细检查(多重共线性)。这只是经验法则;对回归来说,方差膨胀因子(VIF)是更好的检查方法。
Time Series Visualisation 📈Time Series Visualisation 📈时间序列可视化 📈
A time series plot answers three questions at once: Is there a trend? Is there seasonality? Are there sudden spikes or drops? Daily data is noisy, so we add a rolling mean to see the trend. Use a rolling mean on daily (or weekly) points — a "7-day rolling mean" only makes sense when each point is one day.
Time series plot एक साथ तीन सवालों का जवाब देता है: क्या कोई trend है? क्या seasonality है? क्या अचानक उछाल या गिरावट है? रोज़ का data शोर भरा होता है, इसलिए trend देखने के लिए rolling mean जोड़ते हैं। Rolling mean रोज़ के (या हफ़्ते के) points पर लगाएँ — "7-day rolling mean" का मतलब तभी है जब हर point एक दिन हो।
时间序列图同时回答三个问题:有没有趋势?有没有季节性?有没有突然的峰值或骤降?日数据噪声大,所以要加滚动均值来看趋势。滚动均值要用在日(或周)数据上 —— 只有每个点代表一天时,“7 日滚动均值”才有意义。
An upward trend (about ₹40k → ₹60k per day), a festive bump every October–November, small weekly wiggles from busier weekends, and three planted one-day anomalies.
ऊपर जाता trend (लगभग ₹40k → ₹60k प्रति दिन), हर अक्टूबर–नवंबर त्योहारी उभार, व्यस्त weekends से छोटे साप्ताहिक उतार-चढ़ाव, और तीन डाली गई एक-दिन की anomalies।
上升趋势(每天约 ₹40k → ₹60k),每年 10–11 月的节日高峰,周末更忙带来的小幅周波动,以及三个预埋的单日异常。
October and November are the clear seasonal peak, so a forecast must include it. February looks high only because of a single bad record (₹269k on 2025-02-01); without it the average is 48.6. One bad value can change a summary chart.
अक्टूबर और नवंबर साफ़ मौसमी चोटी हैं, इसलिए forecast में इसे शामिल करना ज़रूरी है। फ़रवरी सिर्फ़ एक ग़लत record (2025-02-01 को ₹269k) की वजह से ऊँचा दिखता है; उसके बिना औसत 48.6 है। एक ग़लत मान summary chart बदल सकता है।
10 月和 11 月是明显的季节高峰,预测时必须考虑。2 月看起来偏高,只是因为一条错误记录(2025-02-01 的 ₹269k);去掉它,均值为 48.6。一个坏值就能改变汇总图。
sns.barplot(data=df, x="month", y="revenue") draws the mean of each group by default, plus a 95% confidence-interval error bar (from bootstrapping). Use estimator="median" for skewed data, errorbar=None to hide the bars, or countplot to count rows.
sns.barplot(data=df, x="month", y="revenue") default रूप से हर group का mean बनाता है, साथ में 95% confidence-interval error bar (bootstrapping से)। Skewed data के लिए estimator="median", bars छिपाने के लिए errorbar=None, या rows गिनने के लिए countplot इस्तेमाल करें।
sns.barplot(data=df, x="month", y="revenue") 默认画出每组的均值,并附带 95% 置信区间误差线(通过 bootstrap 计算)。偏态数据用 estimator="median",用 errorbar=None 隐藏误差线,或用 countplot 统计行数。
Identifying Patterns in Data 🧩Data में Patterns पहचानना 🧩识别数据中的规律 🧩
A pattern is anything that repeats, lasts, or follows a rule. Three kinds matter most in data science.
Pattern वह चीज़ है जो दोहराती है, टिकी रहती है, या किसी नियम पर चलती है। Data science में तीन तरह के सबसे ज़रूरी हैं।
规律是任何会重复、会持续或遵循某种规则的东西。数据科学中最重要的有三类。
- Long-term rise or fallलंबे समय की बढ़त या गिरावट长期上升或下降
- Seen in line charts over timeसमय वाले line charts में दिखता है在时间折线图中可见
- Smooth noise with a rolling meanRolling mean से शोर हटाएँ用滚动均值平滑噪声
- Here: ₹40k → ₹60k per dayयहाँ: ₹40k → ₹60k प्रति दिन本例:每天 ₹40k → ₹60k
- A pattern that repeats at fixed intervalsतय अंतराल पर दोहराने वाला pattern以固定间隔重复的模式
- Daily, weekly, monthly or yearlyरोज़ाना, साप्ताहिक, मासिक या सालाना日、周、月或年
- Check with month / weekday chartsमहीने / हफ़्ते के दिन वाले charts से जाँचें用按月 / 按星期的图检查
- Separate it with seasonal decompositionSeasonal decomposition से अलग करें用季节分解把它分离出来
- Natural groups of pointsPoints के प्राकृतिक समूह数据点的自然分组
- Separate clouds in a scatter plotScatter plot में अलग-अलग बादल散点图中分开的点云
- Colour by a known group to test an ideaकिसी ज्ञात group से रंग देकर विचार जाँचें按已知分组上色来检验想法
- May suggest customer segmentsCustomer segments का संकेत दे सकते हैं可能提示客户细分
Spotting Anomalies Visually 🚨Anomalies को देखकर पहचानना 🚨用图发现异常 🚨
An anomaly is a point that does not fit the expected pattern. It may be a data error, a real extreme value, or a real signal — a sale, a fraud attempt, a system outage. Charts are a fast way to find them; deciding what they mean needs domain knowledge.
Anomaly ऐसा point है जो अपेक्षित pattern में फ़िट नहीं होता। यह data की ग़लती, असली अति मान, या असली संकेत हो सकता है — कोई sale, fraud की कोशिश, system outage। Charts इन्हें ढूँढने का तेज़ तरीक़ा हैं; इनका मतलब तय करने के लिए domain knowledge चाहिए।
异常是不符合预期模式的点。它可能是数据错误、真实的极端值,也可能是真实信号 —— 一次促销、一次欺诈尝试、一次系统宕机。图表能快速发现它们;判断它们的含义则需要领域知识。
First ask: is it a data-quality problem (a typo, a unit mix-up, a duplicate load)? Then ask: is it a real event? Removing real extremes can bias your model; keeping errors can break it. Write down every decision.
पहले पूछें: क्या यह data-quality की समस्या है (typo, इकाई की गड़बड़, दोहरा load)? फिर पूछें: क्या यह असली घटना है? असली अति मान हटाने से model biased हो सकता है; ग़लतियाँ रखने से वह टूट सकता है। हर फ़ैसला लिखें।
先问:这是数据质量问题吗(拼写错误、单位混淆、重复导入)?再问:这是真实事件吗?删除真实的极端值会让模型产生偏差;保留错误会让模型失效。把每个决定都记录下来。
base = daily["revenue"].shift(1).rolling(28). Without shift(1), today's spike sits inside its own window, inflates the mean and σ, and can hide itself.base = daily["revenue"].shift(1).rolling(28)। shift(1) के बिना आज का spike अपनी ही window में होता है, mean और σ को बढ़ाता है, और ख़ुद को छिपा सकता है।base = daily["revenue"].shift(1).rolling(28)。没有 shift(1),今天的峰值会落在它自己的窗口里,抬高均值和 σ,从而可能把自己藏起来。upper = base.mean() + k * base.std() and lower = base.mean() - k * base.std(). With k = 3, about 0.3% of normal-looking days would cross by chance; k = 2 gives about 5%, so many more false alarms.upper = base.mean() + k * base.std() और lower = base.mean() - k * base.std()। k = 3 पर लगभग 0.3% सामान्य दिन संयोग से पार करेंगे; k = 2 पर लगभग 5%, यानी कहीं ज़्यादा झूठे alarms।upper = base.mean() + k * base.std(),lower = base.mean() - k * base.std()。k = 3 时,大约 0.3% 的正常日子会偶然越界;k = 2 时约为 5%,误报会多得多。# 4) Time series: rolling mean, monthly pattern, and spike detection
import pandas as pd
daily = pd.read_csv("daily_sales.csv", parse_dates=["date"]).set_index("date")
daily["rolling_7d"] = daily["revenue"].rolling(7).mean()
monthly = daily["revenue"].groupby(daily.index.month).mean().round(1)
print("average daily revenue by month (₹k):"); print(monthly.to_string())
# Control band from the PREVIOUS 28 days (shift(1) keeps today's value out of its own band)
base = daily["revenue"].shift(1).rolling(28)
daily["upper"] = base.mean() + 3 * base.std()
daily["lower"] = base.mean() - 3 * base.std()
spikes = daily[(daily["revenue"] > daily["upper"]) | (daily["revenue"] < daily["lower"])]
print("\nflagged days:"); print(spikes[["revenue", "lower", "upper"]].round(1))
731 days of revenue with 3 planted anomalies (purple rings). Change the window and k, and turn shift on or off. Can you catch all 3 with few false alarms?
3 डाली गई anomalies (बैंगनी घेरे) के साथ 731 दिन की revenue। Window और k बदलें, और shift चालू या बंद करें। क्या आप कम झूठे alarms के साथ तीनों पकड़ सकते हैं?
731 天的收入数据,含 3 个预埋异常(紫色圆圈)。改变窗口和 k,并开关 shift。你能在误报很少的情况下抓住全部 3 个吗?
For people who are not coders, an interactive chart helps: they can hover over a red marker to see the date and value. plotly does this in a few lines:
जो लोग coder नहीं हैं, उनके लिए interactive chart मदद करता है: वे लाल marker पर hover करके date और मान देख सकते हैं। plotly यह कुछ lines में करता है:
对于不写代码的人,交互式图表很有帮助:鼠标悬停在红色标记上就能看到日期和数值。plotly 只需几行即可做到:
# 5) An interactive chart for stakeholders: plotly line + red markers on flagged days
import pandas as pd, plotly.graph_objects as go
daily = pd.read_csv("daily_sales.csv", parse_dates=["date"]).set_index("date")
base = daily["revenue"].shift(1).rolling(28)
daily["upper"] = base.mean() + 3 * base.std()
daily["lower"] = base.mean() - 3 * base.std()
flag = (daily["revenue"] > daily["upper"]) | (daily["revenue"] < daily["lower"])
fig = go.Figure()
fig.add_scatter(x=daily.index, y=daily["upper"], line_width=0, showlegend=False)
fig.add_scatter(x=daily.index, y=daily["lower"], fill="tonexty", line_width=0, name="normal band")
fig.add_scatter(x=daily.index, y=daily["revenue"], name="revenue", line_width=1)
fig.add_scatter(x=daily.index[flag], y=daily["revenue"][flag], mode="markers",
marker=dict(color="red", size=9), name="flagged")
fig.update_layout(title="Daily revenue (₹ thousand)", hovermode="x unified")
fig.write_html("revenue.html") # open in a browser: hover, zoom, pan
print("flagged:", int(flag.sum()), "days traces:", len(fig.data))
Honest Charts — How Charts Mislead 🎭ईमानदार Charts — Charts कैसे भटकाते हैं 🎭诚实的图表 —— 图表如何误导 🎭
The same numbers can tell different stories depending on how they are drawn. Most misleading charts are accidents, not tricks: a default axis, a pie with too many slices, or colours that some readers cannot tell apart.
एक ही संख्याएँ इस पर निर्भर करते हुए अलग कहानियाँ बता सकती हैं कि उन्हें कैसे बनाया गया। ज़्यादातर भटकाने वाले charts चाल नहीं, भूल होते हैं: default axis, बहुत सारे टुकड़ों वाला pie, या ऐसे रंग जिन्हें कुछ पाठक अलग नहीं कर पाते।
同样的数字,画法不同,讲出的故事也不同。大多数误导性图表是无心之失,而不是故意:默认的坐标轴、切片太多的饼图,或部分读者分不清的颜色。
Two bars that differ by 2.2%. Drag the start of the y-axis up and watch the gap grow. Then switch to the pie mode.
दो bars जिनमें 2.2% का अंतर है। Y-axis की शुरुआत ऊपर खींचें और अंतर बढ़ता देखें। फिर pie mode पर जाएँ।
两根柱只差 2.2%。把 y 轴起点往上拖,看差距如何被放大。然后切换到饼图模式。
| Problemसमस्या问题 | Why it misleadsक्यों भटकाता है为什么会误导 | Fixसुधार修正 |
|---|---|---|
| Bar axis not starting at 0Bar axis 0 से शुरू नहीं条形图坐标轴不从 0 开始 | Bar length is the message, so small gaps look hugeBar की लंबाई ही संदेश है, इसलिए छोटे अंतर बड़े दिखते हैं柱长就是信息,小差距看起来很大 | Start bars at 0. Line charts may zoom in, but label the axis clearlyBars 0 से शुरू करें। Line charts zoom कर सकते हैं, पर axis साफ़ लिखें条形图从 0 开始;折线图可以放大,但要清楚标注坐标轴 |
| Too many pie slicesबहुत सारे pie टुकड़े饼图切片太多 | Angles are hard to compareकोणों की तुलना कठिन है角度难以比较 | Sorted bar chartSorted bar chart排序后的条形图 |
| Red–green only coloursसिर्फ़ लाल–हरे रंग只用红绿配色 | About 1 in 12 men has red–green colour-vision deficiencyलगभग 12 में से 1 पुरुष को लाल–हरा रंग-दृष्टि दोष होता है约每 12 名男性中有 1 人存在红绿色觉缺陷 | Colour-blind-safe palettes (viridis, cividis, seaborn "colorblind") plus labels or shapesColour-blind-safe palettes (viridis, cividis, seaborn "colorblind") और labels या आकार色盲友好配色(viridis、cividis、seaborn "colorblind"),再加标签或形状 |
| Rainbow colour map for numbersसंख्याओं के लिए rainbow colour map用彩虹色表示数值 | Brightness jumps create fake edgesचमक के उछाल नक़ली किनारे बनाते हैं亮度跳变会制造假的边界 | Sequential map (viridis); diverging (coolwarm) when 0 is specialSequential map (viridis); जब 0 ख़ास हो तो diverging (coolwarm)顺序色图(viridis);0 有特殊意义时用发散色图(coolwarm) |
| Two y-axesदो y-axes双 y 轴 | The scales are arbitrary, so any two lines can be made to "match"Scales मनमाने होते हैं, इसलिए कोई भी दो lines "मिलती" दिखाई जा सकती हैं刻度是任意的,任何两条线都能被调成“吻合” | Two panels, or index both series to 100दो panels, या दोनों series को 100 पर index करें分成两个面板,或把两条序列都指数化到 100 |
Make the Practice Data Yourself 🐍Practice Data ख़ुद बनाएँ 🐍自己生成练习数据 🐍
Every chart above was drawn from these two files. The patterns (age → income, category → spend, delivery → rating, trend, weekly and festive seasonality, three one-day anomalies) are built in on purpose, so you can check that each chart finds them. Run this first, then the code blocks in Sections 1–7.
ऊपर का हर chart इन दो files से बना है। Patterns (age → income, category → ख़र्च, delivery → rating, trend, साप्ताहिक और त्योहारी seasonality, तीन एक-दिन की anomalies) जानबूझकर डाले गए हैं, ताकि आप जाँच सकें कि हर chart उन्हें ढूँढता है। पहले इसे चलाएँ, फिर Sections 1–7 के code blocks।
上面每张图都来自这两个文件。其中的规律(年龄 → 收入、类别 → 消费、配送 → 评分、趋势、周和节日季节性、三个单日异常)都是有意内置的,这样你可以检验每张图能否找到它们。先运行这段代码,再运行第 1–7 节的代码块。
# 0) Build two practice datasets that contain real patterns to find
import numpy as np, pandas as pd
rng = np.random.default_rng(11)
# --- customers.csv: one row per customer ---
n = 2000
age = rng.integers(18, 66, n)
p_hi = np.clip((age - 18) / 60, 0.05, 0.75) # older -> more likely higher income
income_code = np.minimum(3, rng.binomial(3, p_hi))
brackets = np.array(["Low", "Medium", "High", "Very High"])
cats = rng.choice(["Electronics", "Furniture", "Clothing", "Books", "Grocery"], n, p=[.15, .1, .3, .2, .25])
cat_base = pd.Series({"Electronics": 9.0, "Furniture": 8.7, "Clothing": 7.9, "Books": 7.0, "Grocery": 6.3})[cats].to_numpy()
spend = np.exp(cat_base + 0.35 * income_code + rng.normal(0, 0.45, n)).round(-1)
delivery = rng.integers(1, 11, n)
rating = np.clip(np.round(5.2 - 0.28 * delivery + rng.normal(0, 0.8, n)), 1, 5)
pd.DataFrame({"age": age, "income_bracket": brackets[income_code], "income_code": income_code,
"product_category": cats, "purchase_amount": spend,
"delivery_days": delivery, "rating": rating}).to_csv("customers.csv", index=False)
# --- daily_sales.csv: two years of daily revenue (₹ thousand) ---
days = pd.date_range("2024-01-01", "2025-12-31", freq="D")
t = np.arange(len(days))
trend = 40 + 20 * t / len(days)
weekly = np.where(days.dayofweek >= 5, 1.18, 1.0)
festive = 1 + 0.45 * np.exp(-((days.dayofyear - 305) / 18) ** 2) + 0.25 * np.exp(-((days.dayofyear - 358) / 6) ** 2)
revenue = np.asarray(trend * weekly * festive * rng.normal(1, 0.07, len(days)))
for d, f in [("2024-03-15", 2.2), ("2025-02-01", 5.0), ("2025-06-10", 0.2)]: # flash sale, data error, outage
revenue[days.get_loc(d)] *= f
pd.DataFrame({"date": days, "revenue": revenue.round(2)}).to_csv("daily_sales.csv", index=False)
print("customers.csv:", n, "rows daily_sales.csv:", len(days), "rows")
A common split: seaborn for quick statistical plots during EDA, plotly when people need to hover, zoom or use a dashboard, and matplotlib when you need full control of every detail (seaborn is built on it). These are habits, not rules — all three can do most jobs.
एक आम बँटवारा: EDA के दौरान तेज़ statistical plots के लिए seaborn, जब लोगों को hover, zoom या dashboard चाहिए तब plotly, और हर detail पर पूरा नियंत्रण चाहिए तब matplotlib (seaborn उसी पर बना है)। ये आदतें हैं, नियम नहीं — तीनों ज़्यादातर काम कर सकती हैं।
常见分工:EDA 时用 seaborn 快速画统计图;需要悬停、缩放或做仪表盘时用 plotly;需要完全控制每个细节时用 matplotlib(seaborn 就构建在它之上)。这些是习惯而不是规定 —— 三者都能完成大多数任务。
Golden Rules of Data Visualisation 🏆Data Visualisation के सुनहरे नियम 🏆数据可视化黄金法则 🏆
Visualisation is a form of analysis, not decoration. Before each chart, say what you expect to see; then plot and compare. When the picture and your expectation disagree — a second hump, a curved link, a February that is too high — that gap is often where the most useful finding is.
Visualisation विश्लेषण का एक रूप है, सजावट नहीं। हर chart से पहले बताएँ कि आप क्या देखने की उम्मीद करते हैं; फिर plot करें और तुलना करें। जब तस्वीर और आपकी उम्मीद मेल न खाएँ — दूसरा उभार, मुड़ा हुआ संबंध, ज़रूरत से ज़्यादा ऊँचा फ़रवरी — वही अंतर अक्सर सबसे काम की खोज होता है।
可视化是一种分析,而不是装饰。画每张图之前,先说出你预期会看到什么;然后画图并比较。当图形与预期不符 —— 多出一个峰、一条弯曲的关系、一个过高的 2 月 —— 这个差距往往就是最有价值的发现所在。