PageSourceSearch

https://datascienceplus.com/register/

html datascienceplus.com collected 2026-10-02 03:46:22 UTC 37,849 bytes, 573 lines download raw bytes

1<!doctype html>
2<html lang="en-US">
3<head>
4	<meta charset="UTF-8">
5	<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
6	<link rel="shortcut icon" href="https://datascienceplus.com/wp-content/themes/dsplus/favicon.png?v=2">
7	<link rel="apple-touch-icon" href="https://datascienceplus.com/wp-content/themes/dsplus/favicon.png?v=2">
8		
8<script>
9	(function () {
10		document.documentElement.classList.add('has-js');
11		try {
12			var saved = localStorage.getItem('dsplus-theme');
13			var mode = saved || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark');
14			document.documentElement.setAttribute('data-theme', mode);
15		} catch (e) {}
16	})();
17	</script>
17
18	<title>Create an account &#8211; DataScience+</title>
19<meta name='robots' content='max-image-preview:large' />
20<meta name="google-adsense-account" content="ca-pub-2675292308944066">
21<link rel="alternate" type="application/rss+xml" title="DataScience+ &raquo; Feed" href="https://datascienceplus.com/feed/" />
22<link rel="alternate" type="application/rss+xml" title="DataScience+ &raquo; Comments Feed" href="https://datascienceplus.com/comments/feed/" />
23<style id="wp-img-auto-sizes-contain-inline-css">
24img:is([sizes=auto i],[sizes^="auto," i]){contain-intrinsic-size:3000px 1500px}
25/*# sourceURL=wp-img-auto-sizes-contain-inline-css */
26</style>
27<style id="wp-block-library-inline-css">
28:root{--wp-block-synced-color:#7a00df;--wp-block-synced-color--rgb:122,0,223;--wp-bound-block-color:var(--wp-block-synced-color);--wp-editor-canvas-background:#ddd;--wp-admin-theme-color:#007cba;--wp-admin-theme-color--rgb:0,124,186;--wp-admin-theme-color-darker-10:#006ba1;--wp-admin-theme-color-darker-10--rgb:0,107,160.5;--wp-admin-theme-color-darker-20:#005a87;--wp-admin-theme-color-darker-20--rgb:0,90,135;--wp-admin-border-width-focus:2px}@media (min-resolution:192dpi){:root{--wp-admin-border-width-focus:1.5px}}.wp-element-button{cursor:pointer}:root .has-very-light-gray-background-color{background-color:#eee}:root .has-very-dark-gray-background-color{background-color:#313131}:root .has-very-light-gray-color{color:#eee}:root .has-very-dark-gray-color{color:#313131}:root .has-vivid-green-cyan-to-vivid-cyan-blue-gradient-background{background:linear-gradient(135deg,#00d084,#0693e3)}:root .has-purple-crush-gradient-background{background:linear-gradient(135deg,#34e2e4,#4721fb 50%,#ab1dfe)}:root .has-hazy-dawn-gradient-background{background:linear-gradient(135deg,#faaca8,#dad0ec)}:root .has-subdued-olive-gradient-background{background:linear-gradient(135deg,#fafae1,#67a671)}:root .has-atomic-cream-gradient-background{background:linear-gradient(135deg,#fdd79a,#004a59)}:root .has-nightshade-gradient-background{background:linear-gradient(135deg,#330968,#31cdcf)}:root .has-midnight-gradient-background{background:linear-gradient(135deg,#020381,#2874fc)}:root{--wp--preset--font-size--normal:16px;
28--wp--preset--font-size--huge:42px}.has-regular-font-size{font-size:1em}.has-larger-font-size{font-size:2.625em}.has-normal-font-size{font-size:var(--wp--preset--font-size--normal)}.has-huge-font-size{font-size:var(--wp--preset--font-size--huge)}:root .has-text-align-center{text-align:center}:root .has-text-align-left{text-align:left}:root .has-text-align-right{text-align:right}.has-fit-text{white-space:nowrap!important}#end-resizable-editor-section{display:none}.aligncenter{clear:both}.items-justified-left{justify-content:flex-start}.items-justified-center{justify-content:center}.items-justified-right{justify-content:flex-end}.items-justified-space-between{justify-content:space-between}.screen-reader-text{word-wrap:normal!important;border:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-break:normal!important}.screen-reader-text:focus{background-color:#ddd;clip-path:none;color:#444;display:block;font-size:1em;height:auto;left:5px;line-height:normal;padding:15px 23px 14px;text-decoration:none;top:5px;width:auto;z-index:100000}html :where(.has-border-color){border-style:solid}html :where([style^=border-color],[style*=";border-color"],[style*="; border-color"]){border-style:solid}html :where([style^=border-top-color],[style*=";border-top-color"],[style*="; border-top-color"]){border-top-style:solid}html :where([style^=border-right-color],[style*=";border-right-color"],[style*="; border-right-color"]){border-right-style:solid}html :where([style^=border-bottom-color],[style*=";border-bottom-color"],[style*="; border-bottom-color"]){border-bottom-style:solid}html :where([style^=border-left-color],[style*=";border-left-color"],[style*="; border-left-color"]){border-left-style:solid}html :where([style^=border-width],[style*=";border-width"],[style*="; border-width"]){border-style:solid}html :where([style^=border-top-width],[style*=";border-top-width"],[style*="; border-top-width"]){border-top-style:solid}html :where([style^=border-right-width],[style*=";border-right-width"],[style*="; border-right-width"]){border-right-style:solid}html :where([style^=border-bottom-width],[style*=";border-bottom-width"],[style*="; border-bottom-width"]){border-bottom-style:solid}html :where([style^=border-left-width],[style*=";border-left-width"],[style*="; border-left-width"]){border-left-style:solid}html :where(img[class*=wp-image-]){height:auto;max-width:100%}:where(figure){margin:0 0 1em}html :where(.is-position-sticky){--wp-admin--admin-bar--position-offset:var(--wp-admin--admin-bar--height,0px)}@media screen and (max-width:600px){html :where(.is-position-sticky){--wp-admin--admin-bar--position-offset:0px}}
29
30/*# sourceURL=/wp-includes/css/dist/block-library/common.min.css */
31</style>
32<style id="classic-theme-styles-inline-css">
33/*! This file is auto-generated */
34.wp-block-button__link{color:#fff;background-color:#32373c;border-radius:9999px;box-shadow:none;text-decoration:none;padding:calc(.667em + 2px) calc(1.333em + 2px);font-size:1.125em}.wp-block-file__button{background:#32373c;color:#fff;text-decoration:none}
35/*# sourceURL=/wp-includes/css/classic-themes.min.css */
36</style>
37
38<style id="global-styles-inline-css">
39:root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgb(6,147,227) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgb(252,185,
390) 0%,rgb(255,105,0) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgb(255,105,0) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgb(255, 255, 255), 6px 6px rgb(0, 0, 0);--wp--preset--shadow--crisp: 6px 6px 0px rgb(0, 0, 0);}.wp-block-button{--wp--preset--dimension--25: 25%;--wp--preset--dimension--50: 50%;--wp--preset--dimension--75: 75%;--wp--preset--dimension--100: 100%;}:where(body) { margin: 0; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}body{padding-top: 0px;padding-right: 0px;padding-bottom: 0px;padding-left: 0px;}:root :where(.wp-element-button, .wp-block-button__link){background-color: #32373c;border-width: 0;color: #fff;font-family: inherit;font-size: inherit;font-style: inherit;font-weight: inherit;letter-spacing: inherit;line-height: inherit;padding-top: calc(0.667em + 2px);padding-right: calc(1.333em + 2px);padding-bottom: calc(0.667em + 2px);padding-left: calc(1.333em + 2px);text-decoration: none;text-transform: inherit;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}
39.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}
40/*# sourceURL=global-styles-inline-css */
41</style>
42
43<link rel='stylesheet' id='dsplus-css' href='https://datascienceplus.com/wp-content/themes/dsplus/style.css?ver=1790531047' media='all' />
44<meta name="robots" content="noindex,nofollow">
45<link rel="icon" href="https://datascienceplus.com/wp-content/uploads/2026/07/cropped-favicon-w-32x32.png" sizes="32x32" />
46<link rel="icon" href="https://datascienceplus.com/wp-content/uploads/2026/07/cropped-favicon-w-192x192.png" sizes="192x192" />
47<link rel="apple-touch-icon" href="https://datascienceplus.com/wp-content/uploads/2026/07/cropped-favicon-w-180x180.png" />
48<meta name="msapplication-TileImage" content="https://datascienceplus.com/wp-content/uploads/2026/07/cropped-favicon-w-270x270.png" />
49</head>
50<body class="wp-theme-dsplus">
51
52<a class="skip-link" href="#content">Skip to content</a>
53
54<header class="nav">
55	<div class="nav-inner">
56		<div class="nav-left">
57			<a class="brand" href="https://datascienceplus.com/">data<b>science+</b></a>
58			<span class="nav-sep" aria-hidden="true">/</span>
59			<nav class="acct" aria-label="Account">
60									<a href="https://datascienceplus.com/login/">Log in</a>
61					<span class="acct-sep" aria-hidden="true">&middot;</span>
62					<a href="https://datascienceplus.com/register/">Register</a>
63							</nav>
64		</div>
65
66		<div class="nav-actions">
67			<form class="navsearch" role="search" method="get" action="https://datascienceplus.com/">
68				<button class="navsearch-toggle" type="button" aria-label="Search">
69					<svg class="ic" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true">
70						<circle cx="11" cy="11" r="7"></circle><line x1="20" y1="20" x2="16.65" y2="16.65"></line>
71					</svg>
72				</button>
73				<input type="search" name="s" value="" placeholder="Search" aria-label="Search articles">
74				<button class="navsearch-close" type="button" tabindex="-1" aria-label="Close search">&times;</button>
75			</form>
76			<button class="navicon" id="dsplus-theme-toggle" type="button" title="Toggle theme" aria-label="Toggle theme">&#9680;</button>
77		</div>
78	</div>
79</header>
80
81<main id="content" class="site-main">
82
83<div class="auth-wrap">
84	<div class="auth-card wide">
85		<div class="auth-head">
86			<h1>Create an account</h1>
87			<p class="sub">Join DataScience+ to write and publish R &amp; Python tutorials.</p>
88		</div>
89
90		<p class="auth-intro">
91			Create an account, then use your dashboard to draft and submit articles — it includes a step-by-step publishing guide. Submissions are checked for fit and quality before they go live.		</p>
92
93		
94		<form class="dsp-form dsp-register" method="post" action="https://datascienceplus.com/wp-admin/admin-post.php">
95			<input type="hidden" name="action" value="dsp_register">
96			<input type="hidden" id="_wpnonce" name="_wpnonce" value="7ce14e63a2" /><input type="hidden" name="_wp_http_referer" value="/register/" />			<p class="dsp-hp-wrap" aria-hidden="true"><label>Website<input type="text" name="dsp_hp" tabindex="-1" autocomplete="off"></label></p>
97
98			<section class="dsp-c-sec">
99				<h3>Your account</h3>
100				<div class="dsp-c-card">
101					<div class="field">
102						<label for="user_email">Email</label>
103						<input id="user_email" name="user_email" type="email" value="" autocomplete="email" required>
104					</div>
105					<div class="field-row">
106						<div class="field">
107							<label for="user_login">Username</label>
108							<input id="user_login" name="user_login" type="text" value="" autocomplete="username" aria-describedby="user_login_status" required>
109							<div class="hint" id="user_login_status" aria-live="polite"></div>
110						</div>
111						<div class="field">
112							<label for="user_pass">Password</label>
113							<input id="user_pass" name="user_pass" type="password" minlength="10" placeholder="At least 10 characters" autocomplete="new-password" required>
114						</div>
115					</div>
116				</div>
117			</section>
118
119			<section class="dsp-c-sec">
120				<h3>Your public profile</h3>
121				<div class="dsp-c-card">
122					<div class="field">
123						<label for="display_name">Name</label>
124						<input id="display_name" name="display_name" type="text" value="" autocomplete="name" required>
125						<div class="hint">Shown on your author page and next to your articles.</div>
126					</div>
127					<div class="field">
128						<label for="description">Short bio</label>
129						<div class="char-wrap">
130							<textarea id="description" name="description" rows="3" maxlength="200" required placeholder="A sentence or two about you and what you write about."></textarea>
131							<span class="charcount" aria-hidden="true"></span>
132						</div>
133						<div class="hint">Shown on your author page and next to your articles.</div>
134					</div>
135				</div>
136			</section>
137
138			<div class="dsp-c-footer">
139				<p class="dsp-c-note">
140					By creating an account you acknowledge that you have read, and agree to, the <a href="https://datascienceplus.com/terms-of-service/">Terms of Service</a> and the <a href="https://datascienceplus.com/privacy-policy/">Privacy Policy</a>.				</p>
141				<button class="dsp-btn primary big" type="submit">Create account</button>
142			</div>
143		</form>
144	</div>
145</div>
146
147<script>
148(function () {
149	var ta = document.getElementById('description');
150	var n  = document.querySelector('.char-wrap .charcount');
151	if (ta && n) {
152		var max = parseInt(ta.getAttribute('maxlength'), 10) || 200;
153		var update = function () { n.textContent = ta.value.length + ' / ' + max; };
154		ta.addEventListener('input', update);
155		update();
156	}
157})();
158(function () {
159	var input = document.getElementById('user_login');
160	var status = document.getElementById('user_login_status');
161	if (!input || !status) { return; }
162	var base = status.textContent;
163	var ajaxurl = 'https://datascienceplus.com/wp-admin/admin-ajax.php';
164	var nonce = '8feb07132b';
165	var timer, last = '';
166
167	function set(msg, cls) {
168		status.textContent = msg;
169		status.className = 'hint' + (cls ? ' ' + cls : '');
170	}
171
172	input.addEventListener('input', function () {
173		clearTimeout(timer);
174		var val = input.value.trim();
175		if (!val) { set(base, ''); return; }
176		timer = setTimeout(function () {
177			if (val === last) { return; }
178			last = val;
179			var body = new FormData();
180			body.append('action', 'dsp_check_username');
181			body.append('_ajax_nonce', nonce);
182			body.append('user_login', val);
183			fetch(ajaxurl, { method: 'POST', credentials: 'same-origin', body: body })
184				.then(function (r) { return r.json(); })
185				.then(function (j) {
186					if (val !== input.value.trim()) { return; } // stale response
187					if (!j || !j.success) { set(base, ''); return; }
188					switch (j.data.state) {
189						case 'available': set('Username available.', 'is-ok'); break;
190						case 'taken':     set('That username is taken.', 'is-bad'); break;
191						default:          set('Use letters, numbers and . _ @ - only.', 'is-bad');
192					}
193				})
194				.catch(function () { set(base, ''); });
195		}, 350);
196	});
197})();
198</script>
198
199
200</main><!-- #content -->
201
202<footer class="site-footer">
203	<div class="foot-inner">
204		<div class="foot-top">
205			<div class="foot-about">
206				<a class="foot-brand" href="https://datascienceplus.com/">data<b>science+</b></a>
207				<p>Practical data science tutorials in R and Python — statistics, machine learning, data visualization, and programming — written by a community of more than a hundred contributors since 2015.</p>
208			</div>
209			<nav class="foot-cols" aria-label="Footer">
210				<div class="foot-col">
211					<h2>Follow</h2>
212					<a href="https://x.com/datascienceplus" rel="noopener">X (Twitter)</a>
213					<a href="https://bsky.app/profile/datascienceplus.bsky.social" rel="noopener">Bluesky</a>
214					<a href="https://www.linkedin.com/company/datascienceplus" rel="noopener">LinkedIn</a>
215				</div>
216				<div class="foot-col">
217					<h2>Contribute</h2>
218											<a href="https://datascienceplus.com/write-for-us/">Write for Us</a>
219						<a href="https://datascienceplus.com/register/">Register</a>
220										<a href="https://datascienceplus.com/authors/">Authors</a>
221				</div>
222				<div class="foot-col">
223					<h2>Site</h2>
224					<a href="https://datascienceplus.com/privacy-policy/">Privacy Policy</a>
225					<a href="https://datascienceplus.com/terms-of-service/">Terms of Service</a>
226					<a href="https://datascienceplus.com/contact-us/">Contact</a>
227				</div>
228			</nav>
229		</div>
230		<div class="foot-bottom">© 2015–2026 DataScience+</div>
231	</div>
232</footer>
233
234<script>
235/* Cookieless analytics (StatCounter, sc_client_storage disabled — no cookies,
236   no local storage) loads for every visitor. No in-house consent banner: our
237   own cookies are strictly necessary and the analytics is cookieless. The one
238   thing that does need consent, AdSense on single posts, gets it from Google's
239   own consent message, shown by the ad script (dsp-core/includes/ads.php). */
240(function () {
241	window.sc_project = 10637365;
242	window.sc_invisible = 1;
243	window.sc_security = '74bbea50';
244	window.sc_client_storage = 'disabled';
245	var s = document.createElement('script');
246	s.type = 'text/javascript';
247	s.async = true;
248	s.src = 'https://www.statcounter.com/counter/counter.js';
249	document.body.appendChild(s);
250})();
251</script>
251
252<noscript><div class="statcounter"><a title="Web Analytics" href="https://statcounter.com/" target="_blank"><img class="statcounter" src="https://c.statcounter.com/10637365/0/74bbea50/1/" alt="Web Analytics" referrerPolicy="no-referrer-when-downgrade"></a></div></noscript>
253
254<script>
255/* iPhone Safari paints the strip under its bottom toolbar / home indicator
256   with body's background-color (nothing else — see body rule in style.css).
257   Swap it to the footer panel color while the footer is on screen so the
258   footer visually runs to the rounded bottom edge; var() keeps it in sync
259   with the light/dark toggle. */
260(function () {
261	var footer = document.querySelector('.site-footer');
262	if (!footer || !('IntersectionObserver' in window)) { return; }
263	new IntersectionObserver(function (entries) {
264		document.body.style.backgroundColor = entries[0].isIntersecting ? 'var(--panel-2)' : '';
265	}).observe(footer);
266})();
267
268(function () {
269	var btn = document.getElementById('dsplus-theme-toggle');
270	if (!btn) { return; }
271	btn.addEventListener('click', function () {
272		var cur = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light';
273		var next = cur === 'dark' ? 'light' : 'dark';
274		document.documentElement.setAttribute('data-theme', next);
275		try { localStorage.setItem('dsplus-theme', next); } catch (e) {}
276	});
277})();
278
279/* Mobile: collapse the nav search to an icon; tapping it expands the field. */
280(function () {
281	var nav = document.querySelector('.nav');
282	if (!nav) { return; }
283	var form = nav.querySelector('.navsearch');
284	var toggle = nav.querySelector('.navsearch-toggle');
285	var closeBtn = nav.querySelector('.navsearch-close');
286	var input = form ? form.querySelector('input[type="search"]') : null;
287	if (!form || !toggle || !input) { return; }
288
289	function isMobile() { return window.matchMedia('(max-width: 560px)').matches; }
290	function close() {
291		nav.classList.remove('search-open');
292		input.blur();
293	}
294
295	toggle.addEventListener('click', function (e) {
296		if (!isMobile()) { return; }          // desktop: field is always open, do nothing
297		if (!nav.classList.contains('search-open')) {
298			e.preventDefault();
299			nav.classList.add('search-open');
300			input.focus();
301		}
302	});
303	if (closeBtn) { closeBtn.addEventListener('click', close); }
304	input.addEventListener('keydown', function (e) { if (e.key === 'Escape') { close(); } });
305	document.addEventListener('click', function (e) {
306		if (nav.classList.contains('search-open') && !form.contains(e.target)) { close(); }
307	});
308	window.addEventListener('resize', function () {
309		if (!isMobile()) { nav.classList.remove('search-open'); }
310	});
311})();
312
313/* R/Python switch: swap the results in place (no page reload, no scroll jump). */
314(function () {
315	var browse = document.getElementById('browse');
316	if (!browse || !window.fetch || !window.history.pushState) { return; }
317
318	// Pull the R/Python control up under the sticky nav so results are visible —
319	// but only if it isn't already near the top (avoids a pointless jump).
320	function alignToTop() {
321		var seg = browse.querySelector('.seg-wrap') || browse;
322		var navH = 52, gap = 44; // 52 + 44 = 96px, matches #browse scroll-margin-top
323		var top = seg.getBoundingClientRect().top;
324		if (Math.abs(top - (navH + gap)) > 6) {
325			var reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
326			window.scrollTo({
327				top: window.scrollY + top - navH - gap,
328				behavior: reduce ? 'auto' : 'smooth'
329			});
330		}
331	}
332
333	document.addEventListener('click', function (e) {
334		var a = e.target.closest('.segmented a, .filters a, a.sort-toggle');
335		if (!a || !browse.contains(a)) { return; }
336
337		// Already the active view: don't reload, just scroll up to the control.
338		if (a.classList.contains('on')) { e.preventDefault(); alignToTop(); return; }
339
340		e.preventDefault();
341		var url = a.getAttribute('href');
342		browse.style.opacity = '0.55';
343
344		fetch(url, { credentials: 'same-origin' })
345			.then(function (r) { return r.text(); })
346			.then(function (html) {
347				var doc  = new DOMParser().parseFromString(html, 'text/html');
348				var next = doc.getElementById('browse');
349				if (next) { browse.innerHTML = next.innerHTML; }
350				// The page header above the band lives outside #browse — swap it
351				// too so a category switch updates the whole page. Home uses
352				// .hero where archives use .head, so replace whichever is there
353				// with whichever the fetched page has (home ↔ category both ways).
354				var srcTop = doc.querySelector('.head, .hero');
355				var dstTop = document.querySelector('.head, .hero');
356				if (srcTop && dstTop) {
357					// Swapping hero ↔ head changes the height above the band; shift
358					// scroll by the same amount instantly so the band doesn't
359					// visibly move (alignToTop then has little or nothing to do).
360					var before = browse.getBoundingClientRect().top;
361					dstTop.replaceWith(document.importNode(srcTop, true));
362					var delta = browse.getBoundingClientRect().top - before;
363					// 'instant' overrides the html { scroll-behavior: smooth } rule,
364					// which would otherwise animate this compensation into view.
365					if (delta) { window.scrollTo({ top: Math.max(0, window.scrollY + delta), left: 0, behavior: 'instant' }); }
366				}
367				browse.style.opacity = '';
368				if (doc.title) { document.title = doc.title; }
369				history.pushState(null, '', url.replace('#browse', ''));
370				alignToTop();
371				if (window.dspInitInfinite) { window.dspInitInfinite(); }
372			})
373			.catch(function () { window.location = url; });
374	});
375
376	// Back/forward should reflect the previous view.
377	window.addEventListener('popstate', function () { window.location.reload(); });
378
379	// Arriving fresh from a home chip: the URL carries #browse, so the browser
380	// does an instant native jump that lands the R/Python control too low. Reset
381	// to the top and smooth-scroll it into place, matching the in-place feel.
382	if (window.location.hash === '#browse') {
383		window.scrollTo(0, 0);
384		history.replaceState(null, '', window.location.href.replace('#browse', ''));
385		requestAnimationFrame(function () { requestAnimationFrame(alignToTo
385p); });
386	}
387})();
388
389/* ToC links: eased scroll to the heading. Native CSS smooth scrolling is
390   browser-controlled and lands abruptly on long jumps; this animates with a
391   gentle ease-in-out and a distance-scaled duration instead. */
392(function () {
393	var toc = document.querySelector('.toc');
394	if (!toc) { return; }
395
396	toc.addEventListener('click', function (e) {
397		var a = e.target.closest('a[href^="#"]');
398		if (!a) { return; }
399		var target = document.getElementById(decodeURIComponent(a.getAttribute('href').slice(1)));
400		if (!target) { return; }
401		e.preventDefault();
402		history.pushState(null, '', a.getAttribute('href'));
403
404		var margin = parseFloat(getComputedStyle(target).scrollMarginTop) || 0;
405		var to = window.scrollY + target.getBoundingClientRect().top - margin;
406		to = Math.max(0, Math.min(to, document.documentElement.scrollHeight - window.innerHeight));
407
408		if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
409			window.scrollTo({ top: to, behavior: 'instant' });
410			return;
411		}
412
413		var from = window.scrollY, dist = to - from;
414		var dur = Math.min(750, 320 + Math.abs(dist) * 0.15), start = null;
415		function step(ts) {
416			if (start === null) { start = ts; }
417			var t = Math.min(1, (ts - start) / dur);
418			var ease = t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
419			// 'instant' so the html { scroll-behavior: smooth } rule doesn't
420			// re-smooth each frame's position on top of our animation.
421			window.scrollTo({ top: from + dist * ease, behavior: 'instant' });
422			if (t < 1) { requestAnimationFrame(step); }
423		}
424		requestAnimationFrame(step);
425	});
426})();
427
428/* In-house image lightbox: click a post image to view it full-screen. */
429(function () {
430	var imgs = document.querySelectorAll('.entry-content img');
431	if (!imgs.length) { return; }
432
433	var box, boxImg;
434	function build() {
435		box = document.createElement('div');
436		box.className = 'dsp-lightbox';
437		box.setAttribute('role', 'dialog');
438		box.setAttribute('aria-modal', 'true');
439		box.innerHTML = '<button class="dsp-lightbox-close" aria-label="Close">✕</button><img alt="">';
440		boxImg = box.querySelector('img');
441		box.addEventListener('click', close);
442		document.body.appendChild(box);
443	}
444	function open(src, alt) {
445		if (!box) { build(); }
446		boxImg.src = src;
447		boxImg.alt = alt || '';
448		document.body.style.overflow = 'hidden';
449		requestAnimationFrame(function () { box.classList.add('open'); });
450	}
451	function close() {
452		if (!box) { return; }
453		box.classList.remove('open');
454		document.body.style.overflow = '';
455	}
456
457	imgs.forEach(function (img) {
458		var link = img.closest('a');
459		if (link) {
460			var href = link.getAttribute('href') || '';
461			if (/\.(jpe?g|png|gif|webp|avif)$/i.test(href)) {
462				link.addEventListener('click', function (e) { e.preventDefault(); open(href, img.alt); });
463				return;
464			}
465		}
466		img.addEventListener('click', function () { open(img.currentSrc || img.src, img.alt); });
467	});
468
469	document.addEventListener('keydown', function (e) { if (e.key === 'Escape') { close(); } });
470})();
471
472/* "Show more" pagination: load the next page of cards on click and mark each
473   batch with a "Page N" divider. No-JS readers get the plain link (full reload). */
474(function () {
475	var marker = null, grid = null, page = 1, loading = false;
476
477	function loadNext(e) {
478		if (e) { e.preventDefault(); }
479		if (loading || !marker || !grid) { return; }
480		var url = marker.getAttribute('data-next');
481		if (!url) { return; }
482		loading = true;
483		marker.classList.add('loading');
484		fetch(url, { credentials: 'same-origin' })
485			.then(function (r) { return r.text(); })
486			.then(function (html) {
487				var doc = new DOMParser().parseFromString(html, 'text/html');
488				var newGrid = doc.querySelector('.browse .grid');
489				page += 1;
490
491				var divider = document.createElement('div');
492				divider.className = 'page-divider';
493				divider.innerHTML = '<span>Page ' + page + '</span>';
494				grid.appendChild(divider);
495
496				if (newGrid) {
497					Array.prototype.slice.call(newGrid.children).forEach(function (card) {
498						if (!card.classList || !card.classList.contains('page-divider')) { grid.appendChild(card); }
499					});
500				}
501
502				var ns = doc.querySelector('.infinite-more');
503				var nextUrl = ns ? ns.getAttribute('data-next') : '';
504				if (nextUrl) {
505					marker.setAttribute('data-next', nextUrl);
506					var lk = marker.querySelector('.more-link');
507					if (lk) { lk.setAttribute('href', nextUrl); }
508				} else {
509					marker.parentNode.removeChild(marker);
510					marker = null;
511				}
512				loading = false;
513				if (marker) { marker.classList.remove('loading'); }
514			})
515			.catch(function () { loading = false; if (marker) { marker.classList.remove('loading'); } });
516	}
517
518	window.dspInitInfinite = function () {
519		loading = false;
520		page = 1;
521		marker = document.querySelector('.infinite-more');
522		grid = document.querySelector('.browse .grid');
523		if (!marker || !grid) { return; }
524		var link = marker.querySelector('.more-link');
525		if (link && !marker.dataset.bound) {
526			marker.dataset.bound = '1';
527			link.addEventListener('click', loadNext);
528		}
529	};
530	window.dspInitInfinite();
531})();
532
533/* Copy button on code blocks — copies the code only (excludes <em> output).
534   Also on the publishing guide's code boxes (pre.onb-code). */
535(function () {
536	var pres = document.querySelectorAll('.entry-content pre, pre.onb-code');
537	if (!pres.length || !navigator.clipboard) { return; }
538
539	pres.forEach(function (pre) {
540		var wrap = document.createElement('div');
541		wrap.className = 'codeblock';
542		/* code block with a plot attached below: let it sit flush (no gap) */
543		if (pre.classList.contains('has-plot')) { wrap.classList.add('has-plot'); }
544		if (pre.classList.contains('onb-code')) { wrap.classList.add('onb'); }
545		pre.parentNode.insertBefore(wrap, pre);
546		wrap.appendChild(pre);
547
548		var btn = document.createElement('button');
549		btn.type = 'button';
550		btn.className = 'code-copy';
551		btn.textContent = 'Copy';
552		wrap.appendChild(btn);
553
554		btn.addEventListener('click', function () {
555			var clone = pre.cloneNode(true);
556			clone.querySelectorAll('em').forEach(function (e) { e.remove(); }); // drop output
557			var text = clone.textContent.replace(/\s+$/, '');
558			navigator.clipboard.writeText(text).then(function () {
559				btn.textContent = 'Copied';
560				btn.classList.add('copied');
561				setTimeout(function () { btn.textContent = 'Copy'; btn.classList.remove('copied'); }, 1500);
562			});
563		});
564	});
565})();
566</script>
566
567
568<script type="speculationrules">
569{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/wp-content/uploads/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/dsplus/*","/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]}
570</script>
vendor: 1 bytes, line 570
570
571<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"23b032b1dade4474bdc4348b41582a30","r":1,"spa":2}' crossorigin="anonymous"></script>
571
572</body>
573</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.