{"id":2547,"date":"2026-02-02T10:36:30","date_gmt":"2026-02-02T10:36:30","guid":{"rendered":"https:\/\/demo.materiamedica.net\/demo6\/?p=2547"},"modified":"2026-02-02T10:36:30","modified_gmt":"2026-02-02T10:36:30","slug":"chapter-8-numpy-differences","status":"publish","type":"post","link":"https:\/\/demo.materiamedica.net\/demo6\/chapter-8-numpy-differences\/","title":{"rendered":"Chapter 8: NumPy Differences"},"content":{"rendered":"<h3 dir=\"auto\">1. What do we mean by \u201cdifferences\u201d in NumPy?<\/h3>\n<p dir=\"auto\">\u201cDifferences\u201d means <strong>how values change from one element to the next<\/strong>.<\/p>\n<p dir=\"auto\">In mathematics, this is the <strong>discrete derivative<\/strong> or <strong>first difference<\/strong>:<\/p>\n<p dir=\"auto\">\u0394x[i] = x[i] \u2212 x[i\u22121]<\/p>\n<p dir=\"auto\">NumPy gives you a very fast, vectorized way to compute these differences \u2014 no loops needed.<\/p>\n<p dir=\"auto\">The main function is:<\/p>\n<p dir=\"auto\"><strong>np.diff(arr, n=1, axis=-1)<\/strong><\/p>\n<ul dir=\"auto\">\n<li>n = how many times to difference (1 = first difference, 2 = second difference\u2026)<\/li>\n<li>axis = which direction to compute differences (usually -1 = last axis)<\/li>\n<\/ul>\n<h3 dir=\"auto\">2. Basic usage \u2013 first differences (n=1)<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code># Simple time series: daily temperatures\r\ntemps = np.array([22.5, 23.1, 24.0, 23.8, 25.2, 26.1, 25.7, 24.9])\r\n\r\nprint(\"Original temperatures:\", temps)\r\n\r\ndaily_change = np.diff(temps)\r\nprint(\"Daily changes         :\", daily_change.round(2))\r\n# [ 0.6  0.9 -0.2  1.4  0.9 -0.4 -0.8]\r\n\r\n# Length is one shorter!\r\nprint(\"Original length:\", len(temps))\r\nprint(\"Diff length    :\", len(daily_change))<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Key observation<\/strong>:<\/p>\n<p dir=\"auto\">np.diff() returns an array <strong>one element shorter<\/strong> than the input because it needs a previous value to subtract.<\/p>\n<h3 dir=\"auto\">3. Higher-order differences (n &gt; 1)<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>print(\"First differences :\", daily_change.round(2))\r\nprint(\"Second differences:\", np.diff(temps, n=2).round(2))\r\n# [ 0.3 -1.1  1.6 -0.5 -1.3 -0.4]\r\n\r\nprint(\"Third differences :\", np.diff(temps, n=3).round(2))\r\n# [-1.4  2.7 -2.1 -0.8  0.9]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Real meaning<\/strong>:<\/p>\n<ul dir=\"auto\">\n<li>First difference \u2192 daily change (velocity)<\/li>\n<li>Second difference \u2192 daily acceleration<\/li>\n<li>Third difference \u2192 jerk<\/li>\n<\/ul>\n<p dir=\"auto\">Very useful in physics, finance, and signal processing.<\/p>\n<h3 dir=\"auto\">4. Differences along different axes (2D and higher)<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code># 2D array: sales over 4 weeks for 5 stores\r\nsales = np.array([\r\n    [120, 135, 140, 155],   # store 1\r\n    [200, 190, 210, 220],   # store 2\r\n    [80,  85,  90,  95],    # store 3\r\n    [300, 320, 310, 340],   # store 4\r\n    [150, 160, 155, 170]    # store 5\r\n])\r\n\r\nprint(\"Sales data (stores \u00d7 weeks):\\n\", sales)\r\n\r\n# Week-to-week change for each store (default axis=-1 = along weeks)\r\nweekly_change = np.diff(sales, axis=1)\r\nprint(\"\\nWeekly change per store:\\n\", weekly_change)\r\n\r\n# Store-to-store change in week 1 (axis=0)\r\nstore_change_week1 = np.diff(sales[:, 0])\r\nprint(\"\\nStore-to-store change in week 1:\", store_change_week1)<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">5. Very common realistic patterns you will write<\/h3>\n<p dir=\"auto\"><strong>Pattern 1 \u2013 Daily returns in finance<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>prices = np.array([100, 102, 101, 105, 103, 107, 110])\r\n\r\n# Simple returns\r\nsimple_returns = np.diff(prices) \/ prices[:-1]\r\n\r\n# Log returns (more common in finance)\r\nlog_returns = np.diff(np.log(prices))\r\n\r\nprint(\"Prices      :\", prices)\r\nprint(\"Simple ret  :\", simple_returns.round(4))\r\nprint(\"Log returns :\", log_returns.round(4))<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Pattern 2 \u2013 Detecting changes \/ edges in signals<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code># Simulate a step signal with noise\r\nsignal = np.concatenate([np.ones(50)*5, np.ones(50)*10]) + np.random.normal(0, 0.5, 100)\r\n\r\nchange = np.diff(signal)\r\n\r\nplt.plot(signal, label=\"Signal\", lw=2)\r\nplt.plot(np.arange(1, len(signal)), change, label=\"First difference\", lw=2, alpha=0.8)\r\nplt.axvline(50, color='red', ls='--', label=\"True change point\")\r\nplt.legend()\r\nplt.title(\"Using differences to detect change points\")\r\nplt.show()<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Pattern 3 \u2013 Acceleration from position data<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code># Position of an object over time (simulated)\r\ntime = np.linspace(0, 10, 100)\r\nposition = 0.5 * time**2 + 2 * time + 1   # quadratic motion\r\n\r\nvelocity = np.diff(position) \/ np.diff(time)\r\nacceleration = np.diff(velocity) \/ np.diff(time[:-1])\r\n\r\nplt.plot(time, position, label=\"Position\", lw=2)\r\nplt.plot(time[:-1], velocity, label=\"Velocity\", lw=2)\r\nplt.plot(time[:-2], acceleration, label=\"Acceleration\", lw=2)\r\nplt.legend()\r\nplt.title(\"Position \u2192 Velocity \u2192 Acceleration using np.diff\")\r\nplt.show()<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Pattern 4 \u2013 Percentage change<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>revenue = np.array([1.2e6, 1.35e6, 1.28e6, 1.5e6, 1.7e6])\r\n\r\npct_change = np.diff(revenue) \/ revenue[:-1] * 100\r\n\r\nprint(\"Revenue      :\", revenue)\r\nprint(\"% change     :\", pct_change.round(2))<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">6. Summary \u2013 NumPy Differences Quick Reference<\/h3>\n<div>\n<div dir=\"auto\">\n<table dir=\"auto\">\n<thead>\n<tr>\n<th data-col-size=\"lg\">Function \/ Usage<\/th>\n<th data-col-size=\"lg\">What it computes<\/th>\n<th data-col-size=\"xs\">Length of output<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"lg\">np.diff(arr)<\/td>\n<td data-col-size=\"lg\">first differences along last axis<\/td>\n<td data-col-size=\"xs\">len(arr) \u2212 1<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">np.diff(arr, n=2)<\/td>\n<td data-col-size=\"lg\">second differences<\/td>\n<td data-col-size=\"xs\">len(arr) \u2212 2<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">np.diff(arr, axis=0)<\/td>\n<td data-col-size=\"lg\">differences down columns<\/td>\n<td data-col-size=\"xs\">shape with axis reduced by 1<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">np.diff(arr, axis=1)<\/td>\n<td data-col-size=\"lg\">differences across rows<\/td>\n<td data-col-size=\"xs\">shape with axis reduced by 1<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">np.diff(prices) \/ prices[:-1]<\/td>\n<td data-col-size=\"lg\">simple returns<\/td>\n<td data-col-size=\"xs\">\u2014<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">np.diff(np.log(prices))<\/td>\n<td data-col-size=\"lg\">log returns (preferred in finance)<\/td>\n<td data-col-size=\"xs\">\u2014<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">Final teacher advice (very important)<\/h3>\n<p dir=\"auto\"><strong>Golden rule #1<\/strong> <strong>Never write a loop<\/strong> to compute consecutive differences \u2014 use np.diff().<\/p>\n<p dir=\"auto\"><strong>Golden rule #2<\/strong> Remember: np.diff() makes the array <strong>shorter by n elements<\/strong> \u2014 be careful when aligning with original data.<\/p>\n<p dir=\"auto\"><strong>Golden rule #3<\/strong> For <strong>financial returns<\/strong>, prefer <strong>log returns<\/strong>:<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>log_returns = np.diff(np.log(prices))<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\">They are additive over time and more statistically well-behaved.<\/p>\n<p dir=\"auto\"><strong>Golden rule #4<\/strong> When you want <strong>percentage change<\/strong>, do:<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>pct_change = np.diff(arr) \/ arr[:-1] * 100<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\">Would you like to continue with any of these next?<\/p>\n<ul dir=\"auto\">\n<li>Differences vs gradient vs finite differences<\/li>\n<li>Using differences for outlier\/change point detection<\/li>\n<li>Higher-order differences in time series analysis<\/li>\n<li>Realistic mini-project: analyze stock prices or sensor data<\/li>\n<li>Difference between diff and gradient in multiple dimensions<\/li>\n<\/ul>\n<p dir=\"auto\">Just tell me what you want to focus on next! \ud83d\ude0a<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. What do we mean by \u201cdifferences\u201d in NumPy? \u201cDifferences\u201d means how values change from one element to the next. In mathematics, this is the discrete derivative or first difference: \u0394x[i] = x[i] \u2212&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[75],"tags":[],"class_list":["post-2547","post","type-post","status-publish","format-standard","hentry","category-numpy"],"_links":{"self":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2547","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/comments?post=2547"}],"version-history":[{"count":1,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2547\/revisions"}],"predecessor-version":[{"id":2548,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2547\/revisions\/2548"}],"wp:attachment":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/media?parent=2547"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/categories?post=2547"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/tags?post=2547"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}