Coverage for /usr/lib/python3/dist-packages/scipy/spatial/distance.py: 15%

656 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1""" 

2Distance computations (:mod:`scipy.spatial.distance`) 

3===================================================== 

4 

5.. sectionauthor:: Damian Eads 

6 

7Function reference 

8------------------ 

9 

10Distance matrix computation from a collection of raw observation vectors 

11stored in a rectangular array. 

12 

13.. autosummary:: 

14 :toctree: generated/ 

15 

16 pdist -- pairwise distances between observation vectors. 

17 cdist -- distances between two collections of observation vectors 

18 squareform -- convert distance matrix to a condensed one and vice versa 

19 directed_hausdorff -- directed Hausdorff distance between arrays 

20 

21Predicates for checking the validity of distance matrices, both 

22condensed and redundant. Also contained in this module are functions 

23for computing the number of observations in a distance matrix. 

24 

25.. autosummary:: 

26 :toctree: generated/ 

27 

28 is_valid_dm -- checks for a valid distance matrix 

29 is_valid_y -- checks for a valid condensed distance matrix 

30 num_obs_dm -- # of observations in a distance matrix 

31 num_obs_y -- # of observations in a condensed distance matrix 

32 

33Distance functions between two numeric vectors ``u`` and ``v``. Computing 

34distances over a large collection of vectors is inefficient for these 

35functions. Use ``pdist`` for this purpose. 

36 

37.. autosummary:: 

38 :toctree: generated/ 

39 

40 braycurtis -- the Bray-Curtis distance. 

41 canberra -- the Canberra distance. 

42 chebyshev -- the Chebyshev distance. 

43 cityblock -- the Manhattan distance. 

44 correlation -- the Correlation distance. 

45 cosine -- the Cosine distance. 

46 euclidean -- the Euclidean distance. 

47 jensenshannon -- the Jensen-Shannon distance. 

48 mahalanobis -- the Mahalanobis distance. 

49 minkowski -- the Minkowski distance. 

50 seuclidean -- the normalized Euclidean distance. 

51 sqeuclidean -- the squared Euclidean distance. 

52 

53Distance functions between two boolean vectors (representing sets) ``u`` and 

54``v``. As in the case of numerical vectors, ``pdist`` is more efficient for 

55computing the distances between all pairs. 

56 

57.. autosummary:: 

58 :toctree: generated/ 

59 

60 dice -- the Dice dissimilarity. 

61 hamming -- the Hamming distance. 

62 jaccard -- the Jaccard distance. 

63 kulczynski1 -- the Kulczynski 1 distance. 

64 rogerstanimoto -- the Rogers-Tanimoto dissimilarity. 

65 russellrao -- the Russell-Rao dissimilarity. 

66 sokalmichener -- the Sokal-Michener dissimilarity. 

67 sokalsneath -- the Sokal-Sneath dissimilarity. 

68 yule -- the Yule dissimilarity. 

69 

70:func:`hamming` also operates over discrete numerical vectors. 

71""" 

72 

73# Copyright (C) Damian Eads, 2007-2008. New BSD License. 

74 

75__all__ = [ 

76 'braycurtis', 

77 'canberra', 

78 'cdist', 

79 'chebyshev', 

80 'cityblock', 

81 'correlation', 

82 'cosine', 

83 'dice', 

84 'directed_hausdorff', 

85 'euclidean', 

86 'hamming', 

87 'is_valid_dm', 

88 'is_valid_y', 

89 'jaccard', 

90 'jensenshannon', 

91 'kulczynski1', 

92 'mahalanobis', 

93 'minkowski', 

94 'num_obs_dm', 

95 'num_obs_y', 

96 'pdist', 

97 'rogerstanimoto', 

98 'russellrao', 

99 'seuclidean', 

100 'sokalmichener', 

101 'sokalsneath', 

102 'sqeuclidean', 

103 'squareform', 

104 'yule' 

105] 

106 

107 

108import os 

109import warnings 

110import numpy as np 

111import dataclasses 

112 

113from typing import Optional, Callable 

114 

115from functools import partial 

116from scipy._lib._util import _asarray_validated 

117 

118from . import _distance_wrap 

119from . import _hausdorff 

120from ..linalg import norm 

121from ..special import rel_entr 

122 

123from . import _distance_pybind 

124 

125 

126def _extra_windows_error_checks(x, out, required_shape, **kwargs): 

127 # TODO: remove this function when distutils 

128 # build system is removed because pybind11 error 

129 # handling should suffice per gh-18108 

130 if os.name == "nt" and out is not None: 

131 if out.shape != required_shape: 

132 raise ValueError("Output array has incorrect shape.") 

133 if not out.flags["C_CONTIGUOUS"]: 

134 raise ValueError("Output array must be C-contiguous.") 

135 if not np.can_cast(x.dtype, out.dtype): 

136 raise ValueError("Wrong out dtype.") 

137 if os.name == "nt" and "w" in kwargs: 

138 w = kwargs["w"] 

139 if w is not None: 

140 if (w < 0).sum() > 0: 

141 raise ValueError("Input weights should be all non-negative") 

142 

143 

144def _copy_array_if_base_present(a): 

145 """Copy the array if its base points to a parent array.""" 

146 if a.base is not None: 

147 return a.copy() 

148 return a 

149 

150 

151def _correlation_cdist_wrap(XA, XB, dm, **kwargs): 

152 XA = XA - XA.mean(axis=1, keepdims=True) 

153 XB = XB - XB.mean(axis=1, keepdims=True) 

154 _distance_wrap.cdist_cosine_double_wrap(XA, XB, dm, **kwargs) 

155 

156 

157def _correlation_pdist_wrap(X, dm, **kwargs): 

158 X2 = X - X.mean(axis=1, keepdims=True) 

159 _distance_wrap.pdist_cosine_double_wrap(X2, dm, **kwargs) 

160 

161 

162def _convert_to_type(X, out_type): 

163 return np.ascontiguousarray(X, dtype=out_type) 

164 

165 

166def _nbool_correspond_all(u, v, w=None): 

167 if u.dtype == v.dtype == bool and w is None: 

168 not_u = ~u 

169 not_v = ~v 

170 nff = (not_u & not_v).sum() 

171 nft = (not_u & v).sum() 

172 ntf = (u & not_v).sum() 

173 ntt = (u & v).sum() 

174 else: 

175 dtype = np.result_type(int, u.dtype, v.dtype) 

176 u = u.astype(dtype) 

177 v = v.astype(dtype) 

178 not_u = 1.0 - u 

179 not_v = 1.0 - v 

180 if w is not None: 

181 not_u = w * not_u 

182 u = w * u 

183 nff = (not_u * not_v).sum() 

184 nft = (not_u * v).sum() 

185 ntf = (u * not_v).sum() 

186 ntt = (u * v).sum() 

187 return (nff, nft, ntf, ntt) 

188 

189 

190def _nbool_correspond_ft_tf(u, v, w=None): 

191 if u.dtype == v.dtype == bool and w is None: 

192 not_u = ~u 

193 not_v = ~v 

194 nft = (not_u & v).sum() 

195 ntf = (u & not_v).sum() 

196 else: 

197 dtype = np.result_type(int, u.dtype, v.dtype) 

198 u = u.astype(dtype) 

199 v = v.astype(dtype) 

200 not_u = 1.0 - u 

201 not_v = 1.0 - v 

202 if w is not None: 

203 not_u = w * not_u 

204 u = w * u 

205 nft = (not_u * v).sum() 

206 ntf = (u * not_v).sum() 

207 return (nft, ntf) 

208 

209 

210def _validate_cdist_input(XA, XB, mA, mB, n, metric_info, **kwargs): 

211 # get supported types 

212 types = metric_info.types 

213 # choose best type 

214 typ = types[types.index(XA.dtype)] if XA.dtype in types else types[0] 

215 # validate data 

216 XA = _convert_to_type(XA, out_type=typ) 

217 XB = _convert_to_type(XB, out_type=typ) 

218 

219 # validate kwargs 

220 _validate_kwargs = metric_info.validator 

221 if _validate_kwargs: 

222 kwargs = _validate_kwargs((XA, XB), mA + mB, n, **kwargs) 

223 return XA, XB, typ, kwargs 

224 

225 

226def _validate_weight_with_size(X, m, n, **kwargs): 

227 w = kwargs.pop('w', None) 

228 if w is None: 

229 return kwargs 

230 

231 if w.ndim != 1 or w.shape[0] != n: 

232 raise ValueError("Weights must have same size as input vector. " 

233 f"{w.shape[0]} vs. {n}") 

234 

235 kwargs['w'] = _validate_weights(w) 

236 return kwargs 

237 

238 

239def _validate_hamming_kwargs(X, m, n, **kwargs): 

240 w = kwargs.get('w', np.ones((n,), dtype='double')) 

241 

242 if w.ndim != 1 or w.shape[0] != n: 

243 raise ValueError("Weights must have same size as input vector. %d vs. %d" % (w.shape[0], n)) 

244 

245 kwargs['w'] = _validate_weights(w) 

246 return kwargs 

247 

248 

249def _validate_mahalanobis_kwargs(X, m, n, **kwargs): 

250 VI = kwargs.pop('VI', None) 

251 if VI is None: 

252 if m <= n: 

253 # There are fewer observations than the dimension of 

254 # the observations. 

255 raise ValueError("The number of observations (%d) is too " 

256 "small; the covariance matrix is " 

257 "singular. For observations with %d " 

258 "dimensions, at least %d observations " 

259 "are required." % (m, n, n + 1)) 

260 if isinstance(X, tuple): 

261 X = np.vstack(X) 

262 CV = np.atleast_2d(np.cov(X.astype(np.double, copy=False).T)) 

263 VI = np.linalg.inv(CV).T.copy() 

264 kwargs["VI"] = _convert_to_double(VI) 

265 return kwargs 

266 

267 

268def _validate_minkowski_kwargs(X, m, n, **kwargs): 

269 kwargs = _validate_weight_with_size(X, m, n, **kwargs) 

270 if 'p' not in kwargs: 

271 kwargs['p'] = 2. 

272 else: 

273 if kwargs['p'] <= 0: 

274 raise ValueError("p must be greater than 0") 

275 

276 return kwargs 

277 

278 

279def _validate_pdist_input(X, m, n, metric_info, **kwargs): 

280 # get supported types 

281 types = metric_info.types 

282 # choose best type 

283 typ = types[types.index(X.dtype)] if X.dtype in types else types[0] 

284 # validate data 

285 X = _convert_to_type(X, out_type=typ) 

286 

287 # validate kwargs 

288 _validate_kwargs = metric_info.validator 

289 if _validate_kwargs: 

290 kwargs = _validate_kwargs(X, m, n, **kwargs) 

291 return X, typ, kwargs 

292 

293 

294def _validate_seuclidean_kwargs(X, m, n, **kwargs): 

295 V = kwargs.pop('V', None) 

296 if V is None: 

297 if isinstance(X, tuple): 

298 X = np.vstack(X) 

299 V = np.var(X.astype(np.double, copy=False), axis=0, ddof=1) 

300 else: 

301 V = np.asarray(V, order='c') 

302 if len(V.shape) != 1: 

303 raise ValueError('Variance vector V must ' 

304 'be one-dimensional.') 

305 if V.shape[0] != n: 

306 raise ValueError('Variance vector V must be of the same ' 

307 'dimension as the vectors on which the distances ' 

308 'are computed.') 

309 kwargs['V'] = _convert_to_double(V) 

310 return kwargs 

311 

312 

313def _validate_vector(u, dtype=None): 

314 # XXX Is order='c' really necessary? 

315 u = np.asarray(u, dtype=dtype, order='c') 

316 if u.ndim == 1: 

317 return u 

318 raise ValueError("Input vector should be 1-D.") 

319 

320 

321def _validate_weights(w, dtype=np.double): 

322 w = _validate_vector(w, dtype=dtype) 

323 if np.any(w < 0): 

324 raise ValueError("Input weights should be all non-negative") 

325 return w 

326 

327 

328def directed_hausdorff(u, v, seed=0): 

329 """ 

330 Compute the directed Hausdorff distance between two 2-D arrays. 

331 

332 Distances between pairs are calculated using a Euclidean metric. 

333 

334 Parameters 

335 ---------- 

336 u : (M,N) array_like 

337 Input array. 

338 v : (O,N) array_like 

339 Input array. 

340 seed : int or None 

341 Local `numpy.random.RandomState` seed. Default is 0, a random 

342 shuffling of u and v that guarantees reproducibility. 

343 

344 Returns 

345 ------- 

346 d : double 

347 The directed Hausdorff distance between arrays `u` and `v`, 

348 

349 index_1 : int 

350 index of point contributing to Hausdorff pair in `u` 

351 

352 index_2 : int 

353 index of point contributing to Hausdorff pair in `v` 

354 

355 Raises 

356 ------ 

357 ValueError 

358 An exception is thrown if `u` and `v` do not have 

359 the same number of columns. 

360 

361 See Also 

362 -------- 

363 scipy.spatial.procrustes : Another similarity test for two data sets 

364 

365 Notes 

366 ----- 

367 Uses the early break technique and the random sampling approach 

368 described by [1]_. Although worst-case performance is ``O(m * o)`` 

369 (as with the brute force algorithm), this is unlikely in practice 

370 as the input data would have to require the algorithm to explore 

371 every single point interaction, and after the algorithm shuffles 

372 the input points at that. The best case performance is O(m), which 

373 is satisfied by selecting an inner loop distance that is less than 

374 cmax and leads to an early break as often as possible. The authors 

375 have formally shown that the average runtime is closer to O(m). 

376 

377 .. versionadded:: 0.19.0 

378 

379 References 

380 ---------- 

381 .. [1] A. A. Taha and A. Hanbury, "An efficient algorithm for 

382 calculating the exact Hausdorff distance." IEEE Transactions On 

383 Pattern Analysis And Machine Intelligence, vol. 37 pp. 2153-63, 

384 2015. 

385 

386 Examples 

387 -------- 

388 Find the directed Hausdorff distance between two 2-D arrays of 

389 coordinates: 

390 

391 >>> from scipy.spatial.distance import directed_hausdorff 

392 >>> import numpy as np 

393 >>> u = np.array([(1.0, 0.0), 

394 ... (0.0, 1.0), 

395 ... (-1.0, 0.0), 

396 ... (0.0, -1.0)]) 

397 >>> v = np.array([(2.0, 0.0), 

398 ... (0.0, 2.0), 

399 ... (-2.0, 0.0), 

400 ... (0.0, -4.0)]) 

401 

402 >>> directed_hausdorff(u, v)[0] 

403 2.23606797749979 

404 >>> directed_hausdorff(v, u)[0] 

405 3.0 

406 

407 Find the general (symmetric) Hausdorff distance between two 2-D 

408 arrays of coordinates: 

409 

410 >>> max(directed_hausdorff(u, v)[0], directed_hausdorff(v, u)[0]) 

411 3.0 

412 

413 Find the indices of the points that generate the Hausdorff distance 

414 (the Hausdorff pair): 

415 

416 >>> directed_hausdorff(v, u)[1:] 

417 (3, 3) 

418 

419 """ 

420 u = np.asarray(u, dtype=np.float64, order='c') 

421 v = np.asarray(v, dtype=np.float64, order='c') 

422 if u.shape[1] != v.shape[1]: 

423 raise ValueError('u and v need to have the same ' 

424 'number of columns') 

425 result = _hausdorff.directed_hausdorff(u, v, seed) 

426 return result 

427 

428 

429def minkowski(u, v, p=2, w=None): 

430 """ 

431 Compute the Minkowski distance between two 1-D arrays. 

432 

433 The Minkowski distance between 1-D arrays `u` and `v`, 

434 is defined as 

435 

436 .. math:: 

437 

438 {\\|u-v\\|}_p = (\\sum{|u_i - v_i|^p})^{1/p}. 

439 

440 

441 \\left(\\sum{w_i(|(u_i - v_i)|^p)}\\right)^{1/p}. 

442 

443 Parameters 

444 ---------- 

445 u : (N,) array_like 

446 Input array. 

447 v : (N,) array_like 

448 Input array. 

449 p : scalar 

450 The order of the norm of the difference :math:`{\\|u-v\\|}_p`. Note 

451 that for :math:`0 < p < 1`, the triangle inequality only holds with 

452 an additional multiplicative factor, i.e. it is only a quasi-metric. 

453 w : (N,) array_like, optional 

454 The weights for each value in `u` and `v`. Default is None, 

455 which gives each value a weight of 1.0 

456 

457 Returns 

458 ------- 

459 minkowski : double 

460 The Minkowski distance between vectors `u` and `v`. 

461 

462 Examples 

463 -------- 

464 >>> from scipy.spatial import distance 

465 >>> distance.minkowski([1, 0, 0], [0, 1, 0], 1) 

466 2.0 

467 >>> distance.minkowski([1, 0, 0], [0, 1, 0], 2) 

468 1.4142135623730951 

469 >>> distance.minkowski([1, 0, 0], [0, 1, 0], 3) 

470 1.2599210498948732 

471 >>> distance.minkowski([1, 1, 0], [0, 1, 0], 1) 

472 1.0 

473 >>> distance.minkowski([1, 1, 0], [0, 1, 0], 2) 

474 1.0 

475 >>> distance.minkowski([1, 1, 0], [0, 1, 0], 3) 

476 1.0 

477 

478 """ 

479 u = _validate_vector(u) 

480 v = _validate_vector(v) 

481 if p <= 0: 

482 raise ValueError("p must be greater than 0") 

483 u_v = u - v 

484 if w is not None: 

485 w = _validate_weights(w) 

486 if p == 1: 

487 root_w = w 

488 elif p == 2: 

489 # better precision and speed 

490 root_w = np.sqrt(w) 

491 elif p == np.inf: 

492 root_w = (w != 0) 

493 else: 

494 root_w = np.power(w, 1/p) 

495 u_v = root_w * u_v 

496 dist = norm(u_v, ord=p) 

497 return dist 

498 

499 

500def euclidean(u, v, w=None): 

501 """ 

502 Computes the Euclidean distance between two 1-D arrays. 

503 

504 The Euclidean distance between 1-D arrays `u` and `v`, is defined as 

505 

506 .. math:: 

507 

508 {\\|u-v\\|}_2 

509 

510 \\left(\\sum{(w_i |(u_i - v_i)|^2)}\\right)^{1/2} 

511 

512 Parameters 

513 ---------- 

514 u : (N,) array_like 

515 Input array. 

516 v : (N,) array_like 

517 Input array. 

518 w : (N,) array_like, optional 

519 The weights for each value in `u` and `v`. Default is None, 

520 which gives each value a weight of 1.0 

521 

522 Returns 

523 ------- 

524 euclidean : double 

525 The Euclidean distance between vectors `u` and `v`. 

526 

527 Examples 

528 -------- 

529 >>> from scipy.spatial import distance 

530 >>> distance.euclidean([1, 0, 0], [0, 1, 0]) 

531 1.4142135623730951 

532 >>> distance.euclidean([1, 1, 0], [0, 1, 0]) 

533 1.0 

534 

535 """ 

536 return minkowski(u, v, p=2, w=w) 

537 

538 

539def sqeuclidean(u, v, w=None): 

540 """ 

541 Compute the squared Euclidean distance between two 1-D arrays. 

542 

543 The squared Euclidean distance between `u` and `v` is defined as 

544 

545 .. math:: 

546 

547 \\sum_i{w_i |u_i - v_i|^2} 

548 

549 Parameters 

550 ---------- 

551 u : (N,) array_like 

552 Input array. 

553 v : (N,) array_like 

554 Input array. 

555 w : (N,) array_like, optional 

556 The weights for each value in `u` and `v`. Default is None, 

557 which gives each value a weight of 1.0 

558 

559 Returns 

560 ------- 

561 sqeuclidean : double 

562 The squared Euclidean distance between vectors `u` and `v`. 

563 

564 Examples 

565 -------- 

566 >>> from scipy.spatial import distance 

567 >>> distance.sqeuclidean([1, 0, 0], [0, 1, 0]) 

568 2.0 

569 >>> distance.sqeuclidean([1, 1, 0], [0, 1, 0]) 

570 1.0 

571 

572 """ 

573 # Preserve float dtypes, but convert everything else to np.float64 

574 # for stability. 

575 utype, vtype = None, None 

576 if not (hasattr(u, "dtype") and np.issubdtype(u.dtype, np.inexact)): 

577 utype = np.float64 

578 if not (hasattr(v, "dtype") and np.issubdtype(v.dtype, np.inexact)): 

579 vtype = np.float64 

580 

581 u = _validate_vector(u, dtype=utype) 

582 v = _validate_vector(v, dtype=vtype) 

583 u_v = u - v 

584 u_v_w = u_v # only want weights applied once 

585 if w is not None: 

586 w = _validate_weights(w) 

587 u_v_w = w * u_v 

588 return np.dot(u_v, u_v_w) 

589 

590 

591def correlation(u, v, w=None, centered=True): 

592 """ 

593 Compute the correlation distance between two 1-D arrays. 

594 

595 The correlation distance between `u` and `v`, is 

596 defined as 

597 

598 .. math:: 

599 

600 1 - \\frac{(u - \\bar{u}) \\cdot (v - \\bar{v})} 

601 {{\\|(u - \\bar{u})\\|}_2 {\\|(v - \\bar{v})\\|}_2} 

602 

603 where :math:`\\bar{u}` is the mean of the elements of `u` 

604 and :math:`x \\cdot y` is the dot product of :math:`x` and :math:`y`. 

605 

606 Parameters 

607 ---------- 

608 u : (N,) array_like 

609 Input array. 

610 v : (N,) array_like 

611 Input array. 

612 w : (N,) array_like, optional 

613 The weights for each value in `u` and `v`. Default is None, 

614 which gives each value a weight of 1.0 

615 centered : bool, optional 

616 If True, `u` and `v` will be centered. Default is True. 

617 

618 Returns 

619 ------- 

620 correlation : double 

621 The correlation distance between 1-D array `u` and `v`. 

622 

623 """ 

624 u = _validate_vector(u) 

625 v = _validate_vector(v) 

626 if w is not None: 

627 w = _validate_weights(w) 

628 if centered: 

629 umu = np.average(u, weights=w) 

630 vmu = np.average(v, weights=w) 

631 u = u - umu 

632 v = v - vmu 

633 uv = np.average(u * v, weights=w) 

634 uu = np.average(np.square(u), weights=w) 

635 vv = np.average(np.square(v), weights=w) 

636 dist = 1.0 - uv / np.sqrt(uu * vv) 

637 # Return absolute value to avoid small negative value due to rounding 

638 return np.abs(dist) 

639 

640 

641def cosine(u, v, w=None): 

642 """ 

643 Compute the Cosine distance between 1-D arrays. 

644 

645 The Cosine distance between `u` and `v`, is defined as 

646 

647 .. math:: 

648 

649 1 - \\frac{u \\cdot v} 

650 {\\|u\\|_2 \\|v\\|_2}. 

651 

652 where :math:`u \\cdot v` is the dot product of :math:`u` and 

653 :math:`v`. 

654 

655 Parameters 

656 ---------- 

657 u : (N,) array_like 

658 Input array. 

659 v : (N,) array_like 

660 Input array. 

661 w : (N,) array_like, optional 

662 The weights for each value in `u` and `v`. Default is None, 

663 which gives each value a weight of 1.0 

664 

665 Returns 

666 ------- 

667 cosine : double 

668 The Cosine distance between vectors `u` and `v`. 

669 

670 Examples 

671 -------- 

672 >>> from scipy.spatial import distance 

673 >>> distance.cosine([1, 0, 0], [0, 1, 0]) 

674 1.0 

675 >>> distance.cosine([100, 0, 0], [0, 1, 0]) 

676 1.0 

677 >>> distance.cosine([1, 1, 0], [0, 1, 0]) 

678 0.29289321881345254 

679 

680 """ 

681 # cosine distance is also referred to as 'uncentered correlation', 

682 # or 'reflective correlation' 

683 # clamp the result to 0-2 

684 return max(0, min(correlation(u, v, w=w, centered=False), 2.0)) 

685 

686 

687def hamming(u, v, w=None): 

688 """ 

689 Compute the Hamming distance between two 1-D arrays. 

690 

691 The Hamming distance between 1-D arrays `u` and `v`, is simply the 

692 proportion of disagreeing components in `u` and `v`. If `u` and `v` are 

693 boolean vectors, the Hamming distance is 

694 

695 .. math:: 

696 

697 \\frac{c_{01} + c_{10}}{n} 

698 

699 where :math:`c_{ij}` is the number of occurrences of 

700 :math:`\\mathtt{u[k]} = i` and :math:`\\mathtt{v[k]} = j` for 

701 :math:`k < n`. 

702 

703 Parameters 

704 ---------- 

705 u : (N,) array_like 

706 Input array. 

707 v : (N,) array_like 

708 Input array. 

709 w : (N,) array_like, optional 

710 The weights for each value in `u` and `v`. Default is None, 

711 which gives each value a weight of 1.0 

712 

713 Returns 

714 ------- 

715 hamming : double 

716 The Hamming distance between vectors `u` and `v`. 

717 

718 Examples 

719 -------- 

720 >>> from scipy.spatial import distance 

721 >>> distance.hamming([1, 0, 0], [0, 1, 0]) 

722 0.66666666666666663 

723 >>> distance.hamming([1, 0, 0], [1, 1, 0]) 

724 0.33333333333333331 

725 >>> distance.hamming([1, 0, 0], [2, 0, 0]) 

726 0.33333333333333331 

727 >>> distance.hamming([1, 0, 0], [3, 0, 0]) 

728 0.33333333333333331 

729 

730 """ 

731 u = _validate_vector(u) 

732 v = _validate_vector(v) 

733 if u.shape != v.shape: 

734 raise ValueError('The 1d arrays must have equal lengths.') 

735 u_ne_v = u != v 

736 if w is not None: 

737 w = _validate_weights(w) 

738 if w.shape != u.shape: 

739 raise ValueError("'w' should have the same length as 'u' and 'v'.") 

740 return np.average(u_ne_v, weights=w) 

741 

742 

743def jaccard(u, v, w=None): 

744 """ 

745 Compute the Jaccard-Needham dissimilarity between two boolean 1-D arrays. 

746 

747 The Jaccard-Needham dissimilarity between 1-D boolean arrays `u` and `v`, 

748 is defined as 

749 

750 .. math:: 

751 

752 \\frac{c_{TF} + c_{FT}} 

753 {c_{TT} + c_{FT} + c_{TF}} 

754 

755 where :math:`c_{ij}` is the number of occurrences of 

756 :math:`\\mathtt{u[k]} = i` and :math:`\\mathtt{v[k]} = j` for 

757 :math:`k < n`. 

758 

759 Parameters 

760 ---------- 

761 u : (N,) array_like, bool 

762 Input array. 

763 v : (N,) array_like, bool 

764 Input array. 

765 w : (N,) array_like, optional 

766 The weights for each value in `u` and `v`. Default is None, 

767 which gives each value a weight of 1.0 

768 

769 Returns 

770 ------- 

771 jaccard : double 

772 The Jaccard distance between vectors `u` and `v`. 

773 

774 Notes 

775 ----- 

776 When both `u` and `v` lead to a `0/0` division i.e. there is no overlap 

777 between the items in the vectors the returned distance is 0. See the 

778 Wikipedia page on the Jaccard index [1]_, and this paper [2]_. 

779 

780 .. versionchanged:: 1.2.0 

781 Previously, when `u` and `v` lead to a `0/0` division, the function 

782 would return NaN. This was changed to return 0 instead. 

783 

784 References 

785 ---------- 

786 .. [1] https://en.wikipedia.org/wiki/Jaccard_index 

787 .. [2] S. Kosub, "A note on the triangle inequality for the Jaccard 

788 distance", 2016, :arxiv:`1612.02696` 

789 

790 Examples 

791 -------- 

792 >>> from scipy.spatial import distance 

793 >>> distance.jaccard([1, 0, 0], [0, 1, 0]) 

794 1.0 

795 >>> distance.jaccard([1, 0, 0], [1, 1, 0]) 

796 0.5 

797 >>> distance.jaccard([1, 0, 0], [1, 2, 0]) 

798 0.5 

799 >>> distance.jaccard([1, 0, 0], [1, 1, 1]) 

800 0.66666666666666663 

801 

802 """ 

803 u = _validate_vector(u) 

804 v = _validate_vector(v) 

805 

806 nonzero = np.bitwise_or(u != 0, v != 0) 

807 unequal_nonzero = np.bitwise_and((u != v), nonzero) 

808 if w is not None: 

809 w = _validate_weights(w) 

810 nonzero = w * nonzero 

811 unequal_nonzero = w * unequal_nonzero 

812 a = np.double(unequal_nonzero.sum()) 

813 b = np.double(nonzero.sum()) 

814 return (a / b) if b != 0 else 0 

815 

816 

817def kulczynski1(u, v, *, w=None): 

818 """ 

819 Compute the Kulczynski 1 dissimilarity between two boolean 1-D arrays. 

820 

821 The Kulczynski 1 dissimilarity between two boolean 1-D arrays `u` and `v` 

822 of length ``n``, is defined as 

823 

824 .. math:: 

825 

826 \\frac{c_{11}} 

827 {c_{01} + c_{10}} 

828 

829 where :math:`c_{ij}` is the number of occurrences of 

830 :math:`\\mathtt{u[k]} = i` and :math:`\\mathtt{v[k]} = j` for 

831 :math:`k \\in {0, 1, ..., n-1}`. 

832 

833 Parameters 

834 ---------- 

835 u : (N,) array_like, bool 

836 Input array. 

837 v : (N,) array_like, bool 

838 Input array. 

839 w : (N,) array_like, optional 

840 The weights for each value in `u` and `v`. Default is None, 

841 which gives each value a weight of 1.0 

842 

843 Returns 

844 ------- 

845 kulczynski1 : float 

846 The Kulczynski 1 distance between vectors `u` and `v`. 

847 

848 Notes 

849 ----- 

850 This measure has a minimum value of 0 and no upper limit. 

851 It is un-defined when there are no non-matches. 

852 

853 .. versionadded:: 1.8.0 

854 

855 References 

856 ---------- 

857 .. [1] Kulczynski S. et al. Bulletin 

858 International de l'Academie Polonaise des Sciences 

859 et des Lettres, Classe des Sciences Mathematiques 

860 et Naturelles, Serie B (Sciences Naturelles). 1927; 

861 Supplement II: 57-203. 

862 

863 Examples 

864 -------- 

865 >>> from scipy.spatial import distance 

866 >>> distance.kulczynski1([1, 0, 0], [0, 1, 0]) 

867 0.0 

868 >>> distance.kulczynski1([True, False, False], [True, True, False]) 

869 1.0 

870 >>> distance.kulczynski1([True, False, False], [True]) 

871 0.5 

872 >>> distance.kulczynski1([1, 0, 0], [3, 1, 0]) 

873 -3.0 

874 

875 """ 

876 u = _validate_vector(u) 

877 v = _validate_vector(v) 

878 if w is not None: 

879 w = _validate_weights(w) 

880 (_, nft, ntf, ntt) = _nbool_correspond_all(u, v, w=w) 

881 

882 return ntt / (ntf + nft) 

883 

884 

885def seuclidean(u, v, V): 

886 """ 

887 Return the standardized Euclidean distance between two 1-D arrays. 

888 

889 The standardized Euclidean distance between two n-vectors `u` and `v` is 

890 

891 .. math:: 

892 

893 \\sqrt{\\sum\\limits_i \\frac{1}{V_i} \\left(u_i-v_i \\right)^2} 

894 

895 ``V`` is the variance vector; ``V[I]`` is the variance computed over all the i-th 

896 components of the points. If not passed, it is automatically computed. 

897 

898 Parameters 

899 ---------- 

900 u : (N,) array_like 

901 Input array. 

902 v : (N,) array_like 

903 Input array. 

904 V : (N,) array_like 

905 `V` is an 1-D array of component variances. It is usually computed 

906 among a larger collection vectors. 

907 

908 Returns 

909 ------- 

910 seuclidean : double 

911 The standardized Euclidean distance between vectors `u` and `v`. 

912 

913 Examples 

914 -------- 

915 >>> from scipy.spatial import distance 

916 >>> distance.seuclidean([1, 0, 0], [0, 1, 0], [0.1, 0.1, 0.1]) 

917 4.4721359549995796 

918 >>> distance.seuclidean([1, 0, 0], [0, 1, 0], [1, 0.1, 0.1]) 

919 3.3166247903553998 

920 >>> distance.seuclidean([1, 0, 0], [0, 1, 0], [10, 0.1, 0.1]) 

921 3.1780497164141406 

922 

923 """ 

924 u = _validate_vector(u) 

925 v = _validate_vector(v) 

926 V = _validate_vector(V, dtype=np.float64) 

927 if V.shape[0] != u.shape[0] or u.shape[0] != v.shape[0]: 

928 raise TypeError('V must be a 1-D array of the same dimension ' 

929 'as u and v.') 

930 return euclidean(u, v, w=1/V) 

931 

932 

933def cityblock(u, v, w=None): 

934 """ 

935 Compute the City Block (Manhattan) distance. 

936 

937 Computes the Manhattan distance between two 1-D arrays `u` and `v`, 

938 which is defined as 

939 

940 .. math:: 

941 

942 \\sum_i {\\left| u_i - v_i \\right|}. 

943 

944 Parameters 

945 ---------- 

946 u : (N,) array_like 

947 Input array. 

948 v : (N,) array_like 

949 Input array. 

950 w : (N,) array_like, optional 

951 The weights for each value in `u` and `v`. Default is None, 

952 which gives each value a weight of 1.0 

953 

954 Returns 

955 ------- 

956 cityblock : double 

957 The City Block (Manhattan) distance between vectors `u` and `v`. 

958 

959 Examples 

960 -------- 

961 >>> from scipy.spatial import distance 

962 >>> distance.cityblock([1, 0, 0], [0, 1, 0]) 

963 2 

964 >>> distance.cityblock([1, 0, 0], [0, 2, 0]) 

965 3 

966 >>> distance.cityblock([1, 0, 0], [1, 1, 0]) 

967 1 

968 

969 """ 

970 u = _validate_vector(u) 

971 v = _validate_vector(v) 

972 l1_diff = abs(u - v) 

973 if w is not None: 

974 w = _validate_weights(w) 

975 l1_diff = w * l1_diff 

976 return l1_diff.sum() 

977 

978 

979def mahalanobis(u, v, VI): 

980 """ 

981 Compute the Mahalanobis distance between two 1-D arrays. 

982 

983 The Mahalanobis distance between 1-D arrays `u` and `v`, is defined as 

984 

985 .. math:: 

986 

987 \\sqrt{ (u-v) V^{-1} (u-v)^T } 

988 

989 where ``V`` is the covariance matrix. Note that the argument `VI` 

990 is the inverse of ``V``. 

991 

992 Parameters 

993 ---------- 

994 u : (N,) array_like 

995 Input array. 

996 v : (N,) array_like 

997 Input array. 

998 VI : array_like 

999 The inverse of the covariance matrix. 

1000 

1001 Returns 

1002 ------- 

1003 mahalanobis : double 

1004 The Mahalanobis distance between vectors `u` and `v`. 

1005 

1006 Examples 

1007 -------- 

1008 >>> from scipy.spatial import distance 

1009 >>> iv = [[1, 0.5, 0.5], [0.5, 1, 0.5], [0.5, 0.5, 1]] 

1010 >>> distance.mahalanobis([1, 0, 0], [0, 1, 0], iv) 

1011 1.0 

1012 >>> distance.mahalanobis([0, 2, 0], [0, 1, 0], iv) 

1013 1.0 

1014 >>> distance.mahalanobis([2, 0, 0], [0, 1, 0], iv) 

1015 1.7320508075688772 

1016 

1017 """ 

1018 u = _validate_vector(u) 

1019 v = _validate_vector(v) 

1020 VI = np.atleast_2d(VI) 

1021 delta = u - v 

1022 m = np.dot(np.dot(delta, VI), delta) 

1023 return np.sqrt(m) 

1024 

1025 

1026def chebyshev(u, v, w=None): 

1027 """ 

1028 Compute the Chebyshev distance. 

1029 

1030 Computes the Chebyshev distance between two 1-D arrays `u` and `v`, 

1031 which is defined as 

1032 

1033 .. math:: 

1034 

1035 \\max_i {|u_i-v_i|}. 

1036 

1037 Parameters 

1038 ---------- 

1039 u : (N,) array_like 

1040 Input vector. 

1041 v : (N,) array_like 

1042 Input vector. 

1043 w : (N,) array_like, optional 

1044 Unused, as 'max' is a weightless operation. Here for API consistency. 

1045 

1046 Returns 

1047 ------- 

1048 chebyshev : double 

1049 The Chebyshev distance between vectors `u` and `v`. 

1050 

1051 Examples 

1052 -------- 

1053 >>> from scipy.spatial import distance 

1054 >>> distance.chebyshev([1, 0, 0], [0, 1, 0]) 

1055 1 

1056 >>> distance.chebyshev([1, 1, 0], [0, 1, 0]) 

1057 1 

1058 

1059 """ 

1060 u = _validate_vector(u) 

1061 v = _validate_vector(v) 

1062 if w is not None: 

1063 w = _validate_weights(w) 

1064 has_weight = w > 0 

1065 if has_weight.sum() < w.size: 

1066 u = u[has_weight] 

1067 v = v[has_weight] 

1068 return max(abs(u - v)) 

1069 

1070 

1071def braycurtis(u, v, w=None): 

1072 """ 

1073 Compute the Bray-Curtis distance between two 1-D arrays. 

1074 

1075 Bray-Curtis distance is defined as 

1076 

1077 .. math:: 

1078 

1079 \\sum{|u_i-v_i|} / \\sum{|u_i+v_i|} 

1080 

1081 The Bray-Curtis distance is in the range [0, 1] if all coordinates are 

1082 positive, and is undefined if the inputs are of length zero. 

1083 

1084 Parameters 

1085 ---------- 

1086 u : (N,) array_like 

1087 Input array. 

1088 v : (N,) array_like 

1089 Input array. 

1090 w : (N,) array_like, optional 

1091 The weights for each value in `u` and `v`. Default is None, 

1092 which gives each value a weight of 1.0 

1093 

1094 Returns 

1095 ------- 

1096 braycurtis : double 

1097 The Bray-Curtis distance between 1-D arrays `u` and `v`. 

1098 

1099 Examples 

1100 -------- 

1101 >>> from scipy.spatial import distance 

1102 >>> distance.braycurtis([1, 0, 0], [0, 1, 0]) 

1103 1.0 

1104 >>> distance.braycurtis([1, 1, 0], [0, 1, 0]) 

1105 0.33333333333333331 

1106 

1107 """ 

1108 u = _validate_vector(u) 

1109 v = _validate_vector(v, dtype=np.float64) 

1110 l1_diff = abs(u - v) 

1111 l1_sum = abs(u + v) 

1112 if w is not None: 

1113 w = _validate_weights(w) 

1114 l1_diff = w * l1_diff 

1115 l1_sum = w * l1_sum 

1116 return l1_diff.sum() / l1_sum.sum() 

1117 

1118 

1119def canberra(u, v, w=None): 

1120 """ 

1121 Compute the Canberra distance between two 1-D arrays. 

1122 

1123 The Canberra distance is defined as 

1124 

1125 .. math:: 

1126 

1127 d(u,v) = \\sum_i \\frac{|u_i-v_i|} 

1128 {|u_i|+|v_i|}. 

1129 

1130 Parameters 

1131 ---------- 

1132 u : (N,) array_like 

1133 Input array. 

1134 v : (N,) array_like 

1135 Input array. 

1136 w : (N,) array_like, optional 

1137 The weights for each value in `u` and `v`. Default is None, 

1138 which gives each value a weight of 1.0 

1139 

1140 Returns 

1141 ------- 

1142 canberra : double 

1143 The Canberra distance between vectors `u` and `v`. 

1144 

1145 Notes 

1146 ----- 

1147 When `u[i]` and `v[i]` are 0 for given i, then the fraction 0/0 = 0 is 

1148 used in the calculation. 

1149 

1150 Examples 

1151 -------- 

1152 >>> from scipy.spatial import distance 

1153 >>> distance.canberra([1, 0, 0], [0, 1, 0]) 

1154 2.0 

1155 >>> distance.canberra([1, 1, 0], [0, 1, 0]) 

1156 1.0 

1157 

1158 """ 

1159 u = _validate_vector(u) 

1160 v = _validate_vector(v, dtype=np.float64) 

1161 if w is not None: 

1162 w = _validate_weights(w) 

1163 with np.errstate(invalid='ignore'): 

1164 abs_uv = abs(u - v) 

1165 abs_u = abs(u) 

1166 abs_v = abs(v) 

1167 d = abs_uv / (abs_u + abs_v) 

1168 if w is not None: 

1169 d = w * d 

1170 d = np.nansum(d) 

1171 return d 

1172 

1173 

1174def jensenshannon(p, q, base=None, *, axis=0, keepdims=False): 

1175 """ 

1176 Compute the Jensen-Shannon distance (metric) between 

1177 two probability arrays. This is the square root 

1178 of the Jensen-Shannon divergence. 

1179 

1180 The Jensen-Shannon distance between two probability 

1181 vectors `p` and `q` is defined as, 

1182 

1183 .. math:: 

1184 

1185 \\sqrt{\\frac{D(p \\parallel m) + D(q \\parallel m)}{2}} 

1186 

1187 where :math:`m` is the pointwise mean of :math:`p` and :math:`q` 

1188 and :math:`D` is the Kullback-Leibler divergence. 

1189 

1190 This routine will normalize `p` and `q` if they don't sum to 1.0. 

1191 

1192 Parameters 

1193 ---------- 

1194 p : (N,) array_like 

1195 left probability vector 

1196 q : (N,) array_like 

1197 right probability vector 

1198 base : double, optional 

1199 the base of the logarithm used to compute the output 

1200 if not given, then the routine uses the default base of 

1201 scipy.stats.entropy. 

1202 axis : int, optional 

1203 Axis along which the Jensen-Shannon distances are computed. The default 

1204 is 0. 

1205 

1206 .. versionadded:: 1.7.0 

1207 keepdims : bool, optional 

1208 If this is set to `True`, the reduced axes are left in the 

1209 result as dimensions with size one. With this option, 

1210 the result will broadcast correctly against the input array. 

1211 Default is False. 

1212 

1213 .. versionadded:: 1.7.0 

1214 

1215 Returns 

1216 ------- 

1217 js : double or ndarray 

1218 The Jensen-Shannon distances between `p` and `q` along the `axis`. 

1219 

1220 Notes 

1221 ----- 

1222 

1223 .. versionadded:: 1.2.0 

1224 

1225 Examples 

1226 -------- 

1227 >>> from scipy.spatial import distance 

1228 >>> import numpy as np 

1229 >>> distance.jensenshannon([1.0, 0.0, 0.0], [0.0, 1.0, 0.0], 2.0) 

1230 1.0 

1231 >>> distance.jensenshannon([1.0, 0.0], [0.5, 0.5]) 

1232 0.46450140402245893 

1233 >>> distance.jensenshannon([1.0, 0.0, 0.0], [1.0, 0.0, 0.0]) 

1234 0.0 

1235 >>> a = np.array([[1, 2, 3, 4], 

1236 ... [5, 6, 7, 8], 

1237 ... [9, 10, 11, 12]]) 

1238 >>> b = np.array([[13, 14, 15, 16], 

1239 ... [17, 18, 19, 20], 

1240 ... [21, 22, 23, 24]]) 

1241 >>> distance.jensenshannon(a, b, axis=0) 

1242 array([0.1954288, 0.1447697, 0.1138377, 0.0927636]) 

1243 >>> distance.jensenshannon(a, b, axis=1) 

1244 array([0.1402339, 0.0399106, 0.0201815]) 

1245 

1246 """ 

1247 p = np.asarray(p) 

1248 q = np.asarray(q) 

1249 p = p / np.sum(p, axis=axis, keepdims=True) 

1250 q = q / np.sum(q, axis=axis, keepdims=True) 

1251 m = (p + q) / 2.0 

1252 left = rel_entr(p, m) 

1253 right = rel_entr(q, m) 

1254 left_sum = np.sum(left, axis=axis, keepdims=keepdims) 

1255 right_sum = np.sum(right, axis=axis, keepdims=keepdims) 

1256 js = left_sum + right_sum 

1257 if base is not None: 

1258 js /= np.log(base) 

1259 return np.sqrt(js / 2.0) 

1260 

1261 

1262def yule(u, v, w=None): 

1263 """ 

1264 Compute the Yule dissimilarity between two boolean 1-D arrays. 

1265 

1266 The Yule dissimilarity is defined as 

1267 

1268 .. math:: 

1269 

1270 \\frac{R}{c_{TT} * c_{FF} + \\frac{R}{2}} 

1271 

1272 where :math:`c_{ij}` is the number of occurrences of 

1273 :math:`\\mathtt{u[k]} = i` and :math:`\\mathtt{v[k]} = j` for 

1274 :math:`k < n` and :math:`R = 2.0 * c_{TF} * c_{FT}`. 

1275 

1276 Parameters 

1277 ---------- 

1278 u : (N,) array_like, bool 

1279 Input array. 

1280 v : (N,) array_like, bool 

1281 Input array. 

1282 w : (N,) array_like, optional 

1283 The weights for each value in `u` and `v`. Default is None, 

1284 which gives each value a weight of 1.0 

1285 

1286 Returns 

1287 ------- 

1288 yule : double 

1289 The Yule dissimilarity between vectors `u` and `v`. 

1290 

1291 Examples 

1292 -------- 

1293 >>> from scipy.spatial import distance 

1294 >>> distance.yule([1, 0, 0], [0, 1, 0]) 

1295 2.0 

1296 >>> distance.yule([1, 1, 0], [0, 1, 0]) 

1297 0.0 

1298 

1299 """ 

1300 u = _validate_vector(u) 

1301 v = _validate_vector(v) 

1302 if w is not None: 

1303 w = _validate_weights(w) 

1304 (nff, nft, ntf, ntt) = _nbool_correspond_all(u, v, w=w) 

1305 half_R = ntf * nft 

1306 if half_R == 0: 

1307 return 0.0 

1308 else: 

1309 return float(2.0 * half_R / (ntt * nff + half_R)) 

1310 

1311 

1312def dice(u, v, w=None): 

1313 """ 

1314 Compute the Dice dissimilarity between two boolean 1-D arrays. 

1315 

1316 The Dice dissimilarity between `u` and `v`, is 

1317 

1318 .. math:: 

1319 

1320 \\frac{c_{TF} + c_{FT}} 

1321 {2c_{TT} + c_{FT} + c_{TF}} 

1322 

1323 where :math:`c_{ij}` is the number of occurrences of 

1324 :math:`\\mathtt{u[k]} = i` and :math:`\\mathtt{v[k]} = j` for 

1325 :math:`k < n`. 

1326 

1327 Parameters 

1328 ---------- 

1329 u : (N,) array_like, bool 

1330 Input 1-D array. 

1331 v : (N,) array_like, bool 

1332 Input 1-D array. 

1333 w : (N,) array_like, optional 

1334 The weights for each value in `u` and `v`. Default is None, 

1335 which gives each value a weight of 1.0 

1336 

1337 Returns 

1338 ------- 

1339 dice : double 

1340 The Dice dissimilarity between 1-D arrays `u` and `v`. 

1341 

1342 Notes 

1343 ----- 

1344 This function computes the Dice dissimilarity index. To compute the 

1345 Dice similarity index, convert one to the other with similarity = 

1346 1 - dissimilarity. 

1347 

1348 Examples 

1349 -------- 

1350 >>> from scipy.spatial import distance 

1351 >>> distance.dice([1, 0, 0], [0, 1, 0]) 

1352 1.0 

1353 >>> distance.dice([1, 0, 0], [1, 1, 0]) 

1354 0.3333333333333333 

1355 >>> distance.dice([1, 0, 0], [2, 0, 0]) 

1356 -0.3333333333333333 

1357 

1358 """ 

1359 u = _validate_vector(u) 

1360 v = _validate_vector(v) 

1361 if w is not None: 

1362 w = _validate_weights(w) 

1363 if u.dtype == v.dtype == bool and w is None: 

1364 ntt = (u & v).sum() 

1365 else: 

1366 dtype = np.result_type(int, u.dtype, v.dtype) 

1367 u = u.astype(dtype) 

1368 v = v.astype(dtype) 

1369 if w is None: 

1370 ntt = (u * v).sum() 

1371 else: 

1372 ntt = (u * v * w).sum() 

1373 (nft, ntf) = _nbool_correspond_ft_tf(u, v, w=w) 

1374 return float((ntf + nft) / np.array(2.0 * ntt + ntf + nft)) 

1375 

1376 

1377def rogerstanimoto(u, v, w=None): 

1378 """ 

1379 Compute the Rogers-Tanimoto dissimilarity between two boolean 1-D arrays. 

1380 

1381 The Rogers-Tanimoto dissimilarity between two boolean 1-D arrays 

1382 `u` and `v`, is defined as 

1383 

1384 .. math:: 

1385 \\frac{R} 

1386 {c_{TT} + c_{FF} + R} 

1387 

1388 where :math:`c_{ij}` is the number of occurrences of 

1389 :math:`\\mathtt{u[k]} = i` and :math:`\\mathtt{v[k]} = j` for 

1390 :math:`k < n` and :math:`R = 2(c_{TF} + c_{FT})`. 

1391 

1392 Parameters 

1393 ---------- 

1394 u : (N,) array_like, bool 

1395 Input array. 

1396 v : (N,) array_like, bool 

1397 Input array. 

1398 w : (N,) array_like, optional 

1399 The weights for each value in `u` and `v`. Default is None, 

1400 which gives each value a weight of 1.0 

1401 

1402 Returns 

1403 ------- 

1404 rogerstanimoto : double 

1405 The Rogers-Tanimoto dissimilarity between vectors 

1406 `u` and `v`. 

1407 

1408 Examples 

1409 -------- 

1410 >>> from scipy.spatial import distance 

1411 >>> distance.rogerstanimoto([1, 0, 0], [0, 1, 0]) 

1412 0.8 

1413 >>> distance.rogerstanimoto([1, 0, 0], [1, 1, 0]) 

1414 0.5 

1415 >>> distance.rogerstanimoto([1, 0, 0], [2, 0, 0]) 

1416 -1.0 

1417 

1418 """ 

1419 u = _validate_vector(u) 

1420 v = _validate_vector(v) 

1421 if w is not None: 

1422 w = _validate_weights(w) 

1423 (nff, nft, ntf, ntt) = _nbool_correspond_all(u, v, w=w) 

1424 return float(2.0 * (ntf + nft)) / float(ntt + nff + (2.0 * (ntf + nft))) 

1425 

1426 

1427def russellrao(u, v, w=None): 

1428 """ 

1429 Compute the Russell-Rao dissimilarity between two boolean 1-D arrays. 

1430 

1431 The Russell-Rao dissimilarity between two boolean 1-D arrays, `u` and 

1432 `v`, is defined as 

1433 

1434 .. math:: 

1435 

1436 \\frac{n - c_{TT}} 

1437 {n} 

1438 

1439 where :math:`c_{ij}` is the number of occurrences of 

1440 :math:`\\mathtt{u[k]} = i` and :math:`\\mathtt{v[k]} = j` for 

1441 :math:`k < n`. 

1442 

1443 Parameters 

1444 ---------- 

1445 u : (N,) array_like, bool 

1446 Input array. 

1447 v : (N,) array_like, bool 

1448 Input array. 

1449 w : (N,) array_like, optional 

1450 The weights for each value in `u` and `v`. Default is None, 

1451 which gives each value a weight of 1.0 

1452 

1453 Returns 

1454 ------- 

1455 russellrao : double 

1456 The Russell-Rao dissimilarity between vectors `u` and `v`. 

1457 

1458 Examples 

1459 -------- 

1460 >>> from scipy.spatial import distance 

1461 >>> distance.russellrao([1, 0, 0], [0, 1, 0]) 

1462 1.0 

1463 >>> distance.russellrao([1, 0, 0], [1, 1, 0]) 

1464 0.6666666666666666 

1465 >>> distance.russellrao([1, 0, 0], [2, 0, 0]) 

1466 0.3333333333333333 

1467 

1468 """ 

1469 u = _validate_vector(u) 

1470 v = _validate_vector(v) 

1471 if u.dtype == v.dtype == bool and w is None: 

1472 ntt = (u & v).sum() 

1473 n = float(len(u)) 

1474 elif w is None: 

1475 ntt = (u * v).sum() 

1476 n = float(len(u)) 

1477 else: 

1478 w = _validate_weights(w) 

1479 ntt = (u * v * w).sum() 

1480 n = w.sum() 

1481 return float(n - ntt) / n 

1482 

1483 

1484def sokalmichener(u, v, w=None): 

1485 """ 

1486 Compute the Sokal-Michener dissimilarity between two boolean 1-D arrays. 

1487 

1488 The Sokal-Michener dissimilarity between boolean 1-D arrays `u` and `v`, 

1489 is defined as 

1490 

1491 .. math:: 

1492 

1493 \\frac{R} 

1494 {S + R} 

1495 

1496 where :math:`c_{ij}` is the number of occurrences of 

1497 :math:`\\mathtt{u[k]} = i` and :math:`\\mathtt{v[k]} = j` for 

1498 :math:`k < n`, :math:`R = 2 * (c_{TF} + c_{FT})` and 

1499 :math:`S = c_{FF} + c_{TT}`. 

1500 

1501 Parameters 

1502 ---------- 

1503 u : (N,) array_like, bool 

1504 Input array. 

1505 v : (N,) array_like, bool 

1506 Input array. 

1507 w : (N,) array_like, optional 

1508 The weights for each value in `u` and `v`. Default is None, 

1509 which gives each value a weight of 1.0 

1510 

1511 Returns 

1512 ------- 

1513 sokalmichener : double 

1514 The Sokal-Michener dissimilarity between vectors `u` and `v`. 

1515 

1516 Examples 

1517 -------- 

1518 >>> from scipy.spatial import distance 

1519 >>> distance.sokalmichener([1, 0, 0], [0, 1, 0]) 

1520 0.8 

1521 >>> distance.sokalmichener([1, 0, 0], [1, 1, 0]) 

1522 0.5 

1523 >>> distance.sokalmichener([1, 0, 0], [2, 0, 0]) 

1524 -1.0 

1525 

1526 """ 

1527 u = _validate_vector(u) 

1528 v = _validate_vector(v) 

1529 if w is not None: 

1530 w = _validate_weights(w) 

1531 nff, nft, ntf, ntt = _nbool_correspond_all(u, v, w=w) 

1532 return float(2.0 * (ntf + nft)) / float(ntt + nff + 2.0 * (ntf + nft)) 

1533 

1534 

1535def sokalsneath(u, v, w=None): 

1536 """ 

1537 Compute the Sokal-Sneath dissimilarity between two boolean 1-D arrays. 

1538 

1539 The Sokal-Sneath dissimilarity between `u` and `v`, 

1540 

1541 .. math:: 

1542 

1543 \\frac{R} 

1544 {c_{TT} + R} 

1545 

1546 where :math:`c_{ij}` is the number of occurrences of 

1547 :math:`\\mathtt{u[k]} = i` and :math:`\\mathtt{v[k]} = j` for 

1548 :math:`k < n` and :math:`R = 2(c_{TF} + c_{FT})`. 

1549 

1550 Parameters 

1551 ---------- 

1552 u : (N,) array_like, bool 

1553 Input array. 

1554 v : (N,) array_like, bool 

1555 Input array. 

1556 w : (N,) array_like, optional 

1557 The weights for each value in `u` and `v`. Default is None, 

1558 which gives each value a weight of 1.0 

1559 

1560 Returns 

1561 ------- 

1562 sokalsneath : double 

1563 The Sokal-Sneath dissimilarity between vectors `u` and `v`. 

1564 

1565 Examples 

1566 -------- 

1567 >>> from scipy.spatial import distance 

1568 >>> distance.sokalsneath([1, 0, 0], [0, 1, 0]) 

1569 1.0 

1570 >>> distance.sokalsneath([1, 0, 0], [1, 1, 0]) 

1571 0.66666666666666663 

1572 >>> distance.sokalsneath([1, 0, 0], [2, 1, 0]) 

1573 0.0 

1574 >>> distance.sokalsneath([1, 0, 0], [3, 1, 0]) 

1575 -2.0 

1576 

1577 """ 

1578 u = _validate_vector(u) 

1579 v = _validate_vector(v) 

1580 if u.dtype == v.dtype == bool and w is None: 

1581 ntt = (u & v).sum() 

1582 elif w is None: 

1583 ntt = (u * v).sum() 

1584 else: 

1585 w = _validate_weights(w) 

1586 ntt = (u * v * w).sum() 

1587 (nft, ntf) = _nbool_correspond_ft_tf(u, v, w=w) 

1588 denom = np.array(ntt + 2.0 * (ntf + nft)) 

1589 if not denom.any(): 

1590 raise ValueError('Sokal-Sneath dissimilarity is not defined for ' 

1591 'vectors that are entirely false.') 

1592 return float(2.0 * (ntf + nft)) / denom 

1593 

1594 

1595_convert_to_double = partial(_convert_to_type, out_type=np.double) 

1596_convert_to_bool = partial(_convert_to_type, out_type=bool) 

1597 

1598# adding python-only wrappers to _distance_wrap module 

1599_distance_wrap.pdist_correlation_double_wrap = _correlation_pdist_wrap 

1600_distance_wrap.cdist_correlation_double_wrap = _correlation_cdist_wrap 

1601 

1602 

1603@dataclasses.dataclass(frozen=True) 

1604class CDistMetricWrapper: 

1605 metric_name: str 

1606 

1607 def __call__(self, XA, XB, *, out=None, **kwargs): 

1608 XA = np.ascontiguousarray(XA) 

1609 XB = np.ascontiguousarray(XB) 

1610 mA, n = XA.shape 

1611 mB, _ = XB.shape 

1612 metric_name = self.metric_name 

1613 metric_info = _METRICS[metric_name] 

1614 XA, XB, typ, kwargs = _validate_cdist_input( 

1615 XA, XB, mA, mB, n, metric_info, **kwargs) 

1616 

1617 w = kwargs.pop('w', None) 

1618 if w is not None: 

1619 metric = metric_info.dist_func 

1620 return _cdist_callable( 

1621 XA, XB, metric=metric, out=out, w=w, **kwargs) 

1622 

1623 dm = _prepare_out_argument(out, np.double, (mA, mB)) 

1624 # get cdist wrapper 

1625 cdist_fn = getattr(_distance_wrap, f'cdist_{metric_name}_{typ}_wrap') 

1626 cdist_fn(XA, XB, dm, **kwargs) 

1627 return dm 

1628 

1629 

1630@dataclasses.dataclass(frozen=True) 

1631class CDistWeightedMetricWrapper: 

1632 metric_name: str 

1633 weighted_metric: str 

1634 

1635 def __call__(self, XA, XB, *, out=None, **kwargs): 

1636 XA = np.ascontiguousarray(XA) 

1637 XB = np.ascontiguousarray(XB) 

1638 mA, n = XA.shape 

1639 mB, _ = XB.shape 

1640 metric_name = self.metric_name 

1641 XA, XB, typ, kwargs = _validate_cdist_input( 

1642 XA, XB, mA, mB, n, _METRICS[metric_name], **kwargs) 

1643 dm = _prepare_out_argument(out, np.double, (mA, mB)) 

1644 

1645 w = kwargs.pop('w', None) 

1646 if w is not None: 

1647 metric_name = self.weighted_metric 

1648 kwargs['w'] = w 

1649 

1650 # get cdist wrapper 

1651 cdist_fn = getattr(_distance_wrap, f'cdist_{metric_name}_{typ}_wrap') 

1652 cdist_fn(XA, XB, dm, **kwargs) 

1653 return dm 

1654 

1655 

1656@dataclasses.dataclass(frozen=True) 

1657class PDistMetricWrapper: 

1658 metric_name: str 

1659 

1660 def __call__(self, X, *, out=None, **kwargs): 

1661 X = np.ascontiguousarray(X) 

1662 m, n = X.shape 

1663 metric_name = self.metric_name 

1664 metric_info = _METRICS[metric_name] 

1665 X, typ, kwargs = _validate_pdist_input( 

1666 X, m, n, metric_info, **kwargs) 

1667 out_size = (m * (m - 1)) // 2 

1668 w = kwargs.pop('w', None) 

1669 if w is not None: 

1670 metric = metric_info.dist_func 

1671 return _pdist_callable( 

1672 X, metric=metric, out=out, w=w, **kwargs) 

1673 

1674 dm = _prepare_out_argument(out, np.double, (out_size,)) 

1675 # get pdist wrapper 

1676 pdist_fn = getattr(_distance_wrap, f'pdist_{metric_name}_{typ}_wrap') 

1677 pdist_fn(X, dm, **kwargs) 

1678 return dm 

1679 

1680 

1681@dataclasses.dataclass(frozen=True) 

1682class PDistWeightedMetricWrapper: 

1683 metric_name: str 

1684 weighted_metric: str 

1685 

1686 def __call__(self, X, *, out=None, **kwargs): 

1687 X = np.ascontiguousarray(X) 

1688 m, n = X.shape 

1689 metric_name = self.metric_name 

1690 X, typ, kwargs = _validate_pdist_input( 

1691 X, m, n, _METRICS[metric_name], **kwargs) 

1692 out_size = (m * (m - 1)) // 2 

1693 dm = _prepare_out_argument(out, np.double, (out_size,)) 

1694 

1695 w = kwargs.pop('w', None) 

1696 if w is not None: 

1697 metric_name = self.weighted_metric 

1698 kwargs['w'] = w 

1699 

1700 # get pdist wrapper 

1701 pdist_fn = getattr(_distance_wrap, f'pdist_{metric_name}_{typ}_wrap') 

1702 pdist_fn(X, dm, **kwargs) 

1703 return dm 

1704 

1705 

1706@dataclasses.dataclass(frozen=True) 

1707class MetricInfo: 

1708 # Name of python distance function 

1709 canonical_name: str 

1710 # All aliases, including canonical_name 

1711 aka: set[str] 

1712 # unvectorized distance function 

1713 dist_func: Callable 

1714 # Optimized cdist function 

1715 cdist_func: Callable 

1716 # Optimized pdist function 

1717 pdist_func: Callable 

1718 # function that checks kwargs and computes default values: 

1719 # f(X, m, n, **kwargs) 

1720 validator: Optional[Callable] = None 

1721 # list of supported types: 

1722 # X (pdist) and XA (cdist) are used to choose the type. if there is no 

1723 # match the first type is used. Default double 

1724 types: list[str] = dataclasses.field(default_factory=lambda: ['double']) 

1725 # true if out array must be C-contiguous 

1726 requires_contiguous_out: bool = True 

1727 

1728 

1729# Registry of implemented metrics: 

1730_METRIC_INFOS = [ 

1731 MetricInfo( 

1732 canonical_name='braycurtis', 

1733 aka={'braycurtis'}, 

1734 dist_func=braycurtis, 

1735 cdist_func=_distance_pybind.cdist_braycurtis, 

1736 pdist_func=_distance_pybind.pdist_braycurtis, 

1737 ), 

1738 MetricInfo( 

1739 canonical_name='canberra', 

1740 aka={'canberra'}, 

1741 dist_func=canberra, 

1742 cdist_func=_distance_pybind.cdist_canberra, 

1743 pdist_func=_distance_pybind.pdist_canberra, 

1744 ), 

1745 MetricInfo( 

1746 canonical_name='chebyshev', 

1747 aka={'chebychev', 'chebyshev', 'cheby', 'cheb', 'ch'}, 

1748 dist_func=chebyshev, 

1749 cdist_func=_distance_pybind.cdist_chebyshev, 

1750 pdist_func=_distance_pybind.pdist_chebyshev, 

1751 ), 

1752 MetricInfo( 

1753 canonical_name='cityblock', 

1754 aka={'cityblock', 'cblock', 'cb', 'c'}, 

1755 dist_func=cityblock, 

1756 cdist_func=_distance_pybind.cdist_cityblock, 

1757 pdist_func=_distance_pybind.pdist_cityblock, 

1758 ), 

1759 MetricInfo( 

1760 canonical_name='correlation', 

1761 aka={'correlation', 'co'}, 

1762 dist_func=correlation, 

1763 cdist_func=CDistMetricWrapper('correlation'), 

1764 pdist_func=PDistMetricWrapper('correlation'), 

1765 ), 

1766 MetricInfo( 

1767 canonical_name='cosine', 

1768 aka={'cosine', 'cos'}, 

1769 dist_func=cosine, 

1770 cdist_func=CDistMetricWrapper('cosine'), 

1771 pdist_func=PDistMetricWrapper('cosine'), 

1772 ), 

1773 MetricInfo( 

1774 canonical_name='dice', 

1775 aka={'dice'}, 

1776 types=['bool'], 

1777 dist_func=dice, 

1778 cdist_func=_distance_pybind.cdist_dice, 

1779 pdist_func=_distance_pybind.pdist_dice, 

1780 ), 

1781 MetricInfo( 

1782 canonical_name='euclidean', 

1783 aka={'euclidean', 'euclid', 'eu', 'e'}, 

1784 dist_func=euclidean, 

1785 cdist_func=_distance_pybind.cdist_euclidean, 

1786 pdist_func=_distance_pybind.pdist_euclidean, 

1787 ), 

1788 MetricInfo( 

1789 canonical_name='hamming', 

1790 aka={'matching', 'hamming', 'hamm', 'ha', 'h'}, 

1791 types=['double', 'bool'], 

1792 validator=_validate_hamming_kwargs, 

1793 dist_func=hamming, 

1794 cdist_func=_distance_pybind.cdist_hamming, 

1795 pdist_func=_distance_pybind.pdist_hamming, 

1796 ), 

1797 MetricInfo( 

1798 canonical_name='jaccard', 

1799 aka={'jaccard', 'jacc', 'ja', 'j'}, 

1800 types=['double', 'bool'], 

1801 dist_func=jaccard, 

1802 cdist_func=_distance_pybind.cdist_jaccard, 

1803 pdist_func=_distance_pybind.pdist_jaccard, 

1804 ), 

1805 MetricInfo( 

1806 canonical_name='jensenshannon', 

1807 aka={'jensenshannon', 'js'}, 

1808 dist_func=jensenshannon, 

1809 cdist_func=CDistMetricWrapper('jensenshannon'), 

1810 pdist_func=PDistMetricWrapper('jensenshannon'), 

1811 ), 

1812 MetricInfo( 

1813 canonical_name='kulczynski1', 

1814 aka={'kulczynski1'}, 

1815 types=['bool'], 

1816 dist_func=kulczynski1, 

1817 cdist_func=_distance_pybind.cdist_kulczynski1, 

1818 pdist_func=_distance_pybind.pdist_kulczynski1, 

1819 ), 

1820 MetricInfo( 

1821 canonical_name='mahalanobis', 

1822 aka={'mahalanobis', 'mahal', 'mah'}, 

1823 validator=_validate_mahalanobis_kwargs, 

1824 dist_func=mahalanobis, 

1825 cdist_func=CDistMetricWrapper('mahalanobis'), 

1826 pdist_func=PDistMetricWrapper('mahalanobis'), 

1827 ), 

1828 MetricInfo( 

1829 canonical_name='minkowski', 

1830 aka={'minkowski', 'mi', 'm', 'pnorm'}, 

1831 validator=_validate_minkowski_kwargs, 

1832 dist_func=minkowski, 

1833 cdist_func=_distance_pybind.cdist_minkowski, 

1834 pdist_func=_distance_pybind.pdist_minkowski, 

1835 ), 

1836 MetricInfo( 

1837 canonical_name='rogerstanimoto', 

1838 aka={'rogerstanimoto'}, 

1839 types=['bool'], 

1840 dist_func=rogerstanimoto, 

1841 cdist_func=_distance_pybind.cdist_rogerstanimoto, 

1842 pdist_func=_distance_pybind.pdist_rogerstanimoto, 

1843 ), 

1844 MetricInfo( 

1845 canonical_name='russellrao', 

1846 aka={'russellrao'}, 

1847 types=['bool'], 

1848 dist_func=russellrao, 

1849 cdist_func=_distance_pybind.cdist_russellrao, 

1850 pdist_func=_distance_pybind.pdist_russellrao, 

1851 ), 

1852 MetricInfo( 

1853 canonical_name='seuclidean', 

1854 aka={'seuclidean', 'se', 's'}, 

1855 validator=_validate_seuclidean_kwargs, 

1856 dist_func=seuclidean, 

1857 cdist_func=CDistMetricWrapper('seuclidean'), 

1858 pdist_func=PDistMetricWrapper('seuclidean'), 

1859 ), 

1860 MetricInfo( 

1861 canonical_name='sokalmichener', 

1862 aka={'sokalmichener'}, 

1863 types=['bool'], 

1864 dist_func=sokalmichener, 

1865 cdist_func=_distance_pybind.cdist_sokalmichener, 

1866 pdist_func=_distance_pybind.pdist_sokalmichener, 

1867 ), 

1868 MetricInfo( 

1869 canonical_name='sokalsneath', 

1870 aka={'sokalsneath'}, 

1871 types=['bool'], 

1872 dist_func=sokalsneath, 

1873 cdist_func=_distance_pybind.cdist_sokalsneath, 

1874 pdist_func=_distance_pybind.pdist_sokalsneath, 

1875 ), 

1876 MetricInfo( 

1877 canonical_name='sqeuclidean', 

1878 aka={'sqeuclidean', 'sqe', 'sqeuclid'}, 

1879 dist_func=sqeuclidean, 

1880 cdist_func=_distance_pybind.cdist_sqeuclidean, 

1881 pdist_func=_distance_pybind.pdist_sqeuclidean, 

1882 ), 

1883 MetricInfo( 

1884 canonical_name='yule', 

1885 aka={'yule'}, 

1886 types=['bool'], 

1887 dist_func=yule, 

1888 cdist_func=_distance_pybind.cdist_yule, 

1889 pdist_func=_distance_pybind.pdist_yule, 

1890 ), 

1891] 

1892 

1893_METRICS = {info.canonical_name: info for info in _METRIC_INFOS} 

1894_METRIC_ALIAS = {alias: info 

1895 for info in _METRIC_INFOS 

1896 for alias in info.aka} 

1897 

1898_METRICS_NAMES = list(_METRICS.keys()) 

1899 

1900_TEST_METRICS = {'test_' + info.canonical_name: info for info in _METRIC_INFOS} 

1901 

1902 

1903def pdist(X, metric='euclidean', *, out=None, **kwargs): 

1904 """ 

1905 Pairwise distances between observations in n-dimensional space. 

1906 

1907 See Notes for common calling conventions. 

1908 

1909 Parameters 

1910 ---------- 

1911 X : array_like 

1912 An m by n array of m original observations in an 

1913 n-dimensional space. 

1914 metric : str or function, optional 

1915 The distance metric to use. The distance function can 

1916 be 'braycurtis', 'canberra', 'chebyshev', 'cityblock', 

1917 'correlation', 'cosine', 'dice', 'euclidean', 'hamming', 

1918 'jaccard', 'jensenshannon', 'kulczynski1', 

1919 'mahalanobis', 'matching', 'minkowski', 'rogerstanimoto', 

1920 'russellrao', 'seuclidean', 'sokalmichener', 'sokalsneath', 

1921 'sqeuclidean', 'yule'. 

1922 out : ndarray 

1923 The output array. 

1924 If not None, condensed distance matrix Y is stored in this array. 

1925 **kwargs : dict, optional 

1926 Extra arguments to `metric`: refer to each metric documentation for a 

1927 list of all possible arguments. 

1928 

1929 Some possible arguments: 

1930 

1931 p : scalar 

1932 The p-norm to apply for Minkowski, weighted and unweighted. 

1933 Default: 2. 

1934 

1935 w : ndarray 

1936 The weight vector for metrics that support weights (e.g., Minkowski). 

1937 

1938 V : ndarray 

1939 The variance vector for standardized Euclidean. 

1940 Default: var(X, axis=0, ddof=1) 

1941 

1942 VI : ndarray 

1943 The inverse of the covariance matrix for Mahalanobis. 

1944 Default: inv(cov(X.T)).T 

1945 

1946 Returns 

1947 ------- 

1948 Y : ndarray 

1949 Returns a condensed distance matrix Y. For each :math:`i` and :math:`j` 

1950 (where :math:`i<j<m`),where m is the number of original observations. 

1951 The metric ``dist(u=X[i], v=X[j])`` is computed and stored in entry ``m 

1952 * i + j - ((i + 2) * (i + 1)) // 2``. 

1953 

1954 See Also 

1955 -------- 

1956 squareform : converts between condensed distance matrices and 

1957 square distance matrices. 

1958 

1959 Notes 

1960 ----- 

1961 See ``squareform`` for information on how to calculate the index of 

1962 this entry or to convert the condensed distance matrix to a 

1963 redundant square matrix. 

1964 

1965 The following are common calling conventions. 

1966 

1967 1. ``Y = pdist(X, 'euclidean')`` 

1968 

1969 Computes the distance between m points using Euclidean distance 

1970 (2-norm) as the distance metric between the points. The points 

1971 are arranged as m n-dimensional row vectors in the matrix X. 

1972 

1973 2. ``Y = pdist(X, 'minkowski', p=2.)`` 

1974 

1975 Computes the distances using the Minkowski distance 

1976 :math:`\\|u-v\\|_p` (:math:`p`-norm) where :math:`p > 0` (note 

1977 that this is only a quasi-metric if :math:`0 < p < 1`). 

1978 

1979 3. ``Y = pdist(X, 'cityblock')`` 

1980 

1981 Computes the city block or Manhattan distance between the 

1982 points. 

1983 

1984 4. ``Y = pdist(X, 'seuclidean', V=None)`` 

1985 

1986 Computes the standardized Euclidean distance. The standardized 

1987 Euclidean distance between two n-vectors ``u`` and ``v`` is 

1988 

1989 .. math:: 

1990 

1991 \\sqrt{\\sum {(u_i-v_i)^2 / V[x_i]}} 

1992 

1993 

1994 V is the variance vector; V[i] is the variance computed over all 

1995 the i'th components of the points. If not passed, it is 

1996 automatically computed. 

1997 

1998 5. ``Y = pdist(X, 'sqeuclidean')`` 

1999 

2000 Computes the squared Euclidean distance :math:`\\|u-v\\|_2^2` between 

2001 the vectors. 

2002 

2003 6. ``Y = pdist(X, 'cosine')`` 

2004 

2005 Computes the cosine distance between vectors u and v, 

2006 

2007 .. math:: 

2008 

2009 1 - \\frac{u \\cdot v} 

2010 {{\\|u\\|}_2 {\\|v\\|}_2} 

2011 

2012 where :math:`\\|*\\|_2` is the 2-norm of its argument ``*``, and 

2013 :math:`u \\cdot v` is the dot product of ``u`` and ``v``. 

2014 

2015 7. ``Y = pdist(X, 'correlation')`` 

2016 

2017 Computes the correlation distance between vectors u and v. This is 

2018 

2019 .. math:: 

2020 

2021 1 - \\frac{(u - \\bar{u}) \\cdot (v - \\bar{v})} 

2022 {{\\|(u - \\bar{u})\\|}_2 {\\|(v - \\bar{v})\\|}_2} 

2023 

2024 where :math:`\\bar{v}` is the mean of the elements of vector v, 

2025 and :math:`x \\cdot y` is the dot product of :math:`x` and :math:`y`. 

2026 

2027 8. ``Y = pdist(X, 'hamming')`` 

2028 

2029 Computes the normalized Hamming distance, or the proportion of 

2030 those vector elements between two n-vectors ``u`` and ``v`` 

2031 which disagree. To save memory, the matrix ``X`` can be of type 

2032 boolean. 

2033 

2034 9. ``Y = pdist(X, 'jaccard')`` 

2035 

2036 Computes the Jaccard distance between the points. Given two 

2037 vectors, ``u`` and ``v``, the Jaccard distance is the 

2038 proportion of those elements ``u[i]`` and ``v[i]`` that 

2039 disagree. 

2040 

2041 10. ``Y = pdist(X, 'jensenshannon')`` 

2042 

2043 Computes the Jensen-Shannon distance between two probability arrays. 

2044 Given two probability vectors, :math:`p` and :math:`q`, the 

2045 Jensen-Shannon distance is 

2046 

2047 .. math:: 

2048 

2049 \\sqrt{\\frac{D(p \\parallel m) + D(q \\parallel m)}{2}} 

2050 

2051 where :math:`m` is the pointwise mean of :math:`p` and :math:`q` 

2052 and :math:`D` is the Kullback-Leibler divergence. 

2053 

2054 11. ``Y = pdist(X, 'chebyshev')`` 

2055 

2056 Computes the Chebyshev distance between the points. The 

2057 Chebyshev distance between two n-vectors ``u`` and ``v`` is the 

2058 maximum norm-1 distance between their respective elements. More 

2059 precisely, the distance is given by 

2060 

2061 .. math:: 

2062 

2063 d(u,v) = \\max_i {|u_i-v_i|} 

2064 

2065 12. ``Y = pdist(X, 'canberra')`` 

2066 

2067 Computes the Canberra distance between the points. The 

2068 Canberra distance between two points ``u`` and ``v`` is 

2069 

2070 .. math:: 

2071 

2072 d(u,v) = \\sum_i \\frac{|u_i-v_i|} 

2073 {|u_i|+|v_i|} 

2074 

2075 

2076 13. ``Y = pdist(X, 'braycurtis')`` 

2077 

2078 Computes the Bray-Curtis distance between the points. The 

2079 Bray-Curtis distance between two points ``u`` and ``v`` is 

2080 

2081 

2082 .. math:: 

2083 

2084 d(u,v) = \\frac{\\sum_i {|u_i-v_i|}} 

2085 {\\sum_i {|u_i+v_i|}} 

2086 

2087 14. ``Y = pdist(X, 'mahalanobis', VI=None)`` 

2088 

2089 Computes the Mahalanobis distance between the points. The 

2090 Mahalanobis distance between two points ``u`` and ``v`` is 

2091 :math:`\\sqrt{(u-v)(1/V)(u-v)^T}` where :math:`(1/V)` (the ``VI`` 

2092 variable) is the inverse covariance. If ``VI`` is not None, 

2093 ``VI`` will be used as the inverse covariance matrix. 

2094 

2095 15. ``Y = pdist(X, 'yule')`` 

2096 

2097 Computes the Yule distance between each pair of boolean 

2098 vectors. (see yule function documentation) 

2099 

2100 16. ``Y = pdist(X, 'matching')`` 

2101 

2102 Synonym for 'hamming'. 

2103 

2104 17. ``Y = pdist(X, 'dice')`` 

2105 

2106 Computes the Dice distance between each pair of boolean 

2107 vectors. (see dice function documentation) 

2108 

2109 18. ``Y = pdist(X, 'kulczynski1')`` 

2110 

2111 Computes the kulczynski1 distance between each pair of 

2112 boolean vectors. (see kulczynski1 function documentation) 

2113 

2114 19. ``Y = pdist(X, 'rogerstanimoto')`` 

2115 

2116 Computes the Rogers-Tanimoto distance between each pair of 

2117 boolean vectors. (see rogerstanimoto function documentation) 

2118 

2119 20. ``Y = pdist(X, 'russellrao')`` 

2120 

2121 Computes the Russell-Rao distance between each pair of 

2122 boolean vectors. (see russellrao function documentation) 

2123 

2124 21. ``Y = pdist(X, 'sokalmichener')`` 

2125 

2126 Computes the Sokal-Michener distance between each pair of 

2127 boolean vectors. (see sokalmichener function documentation) 

2128 

2129 22. ``Y = pdist(X, 'sokalsneath')`` 

2130 

2131 Computes the Sokal-Sneath distance between each pair of 

2132 boolean vectors. (see sokalsneath function documentation) 

2133 

2134 23. ``Y = pdist(X, 'kulczynski1')`` 

2135 

2136 Computes the Kulczynski 1 distance between each pair of 

2137 boolean vectors. (see kulczynski1 function documentation) 

2138 

2139 24. ``Y = pdist(X, f)`` 

2140 

2141 Computes the distance between all pairs of vectors in X 

2142 using the user supplied 2-arity function f. For example, 

2143 Euclidean distance between the vectors could be computed 

2144 as follows:: 

2145 

2146 dm = pdist(X, lambda u, v: np.sqrt(((u-v)**2).sum())) 

2147 

2148 Note that you should avoid passing a reference to one of 

2149 the distance functions defined in this library. For example,:: 

2150 

2151 dm = pdist(X, sokalsneath) 

2152 

2153 would calculate the pair-wise distances between the vectors in 

2154 X using the Python function sokalsneath. This would result in 

2155 sokalsneath being called :math:`{n \\choose 2}` times, which 

2156 is inefficient. Instead, the optimized C version is more 

2157 efficient, and we call it using the following syntax.:: 

2158 

2159 dm = pdist(X, 'sokalsneath') 

2160 

2161 Examples 

2162 -------- 

2163 >>> import numpy as np 

2164 >>> from scipy.spatial.distance import pdist 

2165 

2166 ``x`` is an array of five points in three-dimensional space. 

2167 

2168 >>> x = np.array([[2, 0, 2], [2, 2, 3], [-2, 4, 5], [0, 1, 9], [2, 2, 4]]) 

2169 

2170 ``pdist(x)`` with no additional arguments computes the 10 pairwise 

2171 Euclidean distances: 

2172 

2173 >>> pdist(x) 

2174 array([2.23606798, 6.40312424, 7.34846923, 2.82842712, 4.89897949, 

2175 6.40312424, 1. , 5.38516481, 4.58257569, 5.47722558]) 

2176 

2177 The following computes the pairwise Minkowski distances with ``p = 3.5``: 

2178 

2179 >>> pdist(x, metric='minkowski', p=3.5) 

2180 array([2.04898923, 5.1154929 , 7.02700737, 2.43802731, 4.19042714, 

2181 6.03956994, 1. , 4.45128103, 4.10636143, 5.0619695 ]) 

2182 

2183 The pairwise city block or Manhattan distances: 

2184 

2185 >>> pdist(x, metric='cityblock') 

2186 array([ 3., 11., 10., 4., 8., 9., 1., 9., 7., 8.]) 

2187 

2188 """ 

2189 # You can also call this as: 

2190 # Y = pdist(X, 'test_abc') 

2191 # where 'abc' is the metric being tested. This computes the distance 

2192 # between all pairs of vectors in X using the distance metric 'abc' but 

2193 # with a more succinct, verifiable, but less efficient implementation. 

2194 

2195 X = _asarray_validated(X, sparse_ok=False, objects_ok=True, mask_ok=True, 

2196 check_finite=False) 

2197 

2198 s = X.shape 

2199 if len(s) != 2: 

2200 raise ValueError('A 2-dimensional array must be passed.') 

2201 

2202 m, n = s 

2203 

2204 if callable(metric): 

2205 mstr = getattr(metric, '__name__', 'UnknownCustomMetric') 

2206 metric_info = _METRIC_ALIAS.get(mstr, None) 

2207 

2208 if metric_info is not None: 

2209 X, typ, kwargs = _validate_pdist_input( 

2210 X, m, n, metric_info, **kwargs) 

2211 

2212 return _pdist_callable(X, metric=metric, out=out, **kwargs) 

2213 elif isinstance(metric, str): 

2214 mstr = metric.lower() 

2215 metric_info = _METRIC_ALIAS.get(mstr, None) 

2216 

2217 if metric_info is not None: 

2218 pdist_fn = metric_info.pdist_func 

2219 _extra_windows_error_checks(X, out, (m * (m - 1) / 2,), **kwargs) 

2220 return pdist_fn(X, out=out, **kwargs) 

2221 elif mstr.startswith("test_"): 

2222 metric_info = _TEST_METRICS.get(mstr, None) 

2223 if metric_info is None: 

2224 raise ValueError(f'Unknown "Test" Distance Metric: {mstr[5:]}') 

2225 X, typ, kwargs = _validate_pdist_input( 

2226 X, m, n, metric_info, **kwargs) 

2227 return _pdist_callable( 

2228 X, metric=metric_info.dist_func, out=out, **kwargs) 

2229 else: 

2230 raise ValueError('Unknown Distance Metric: %s' % mstr) 

2231 else: 

2232 raise TypeError('2nd argument metric must be a string identifier ' 

2233 'or a function.') 

2234 

2235 

2236def squareform(X, force="no", checks=True): 

2237 """ 

2238 Convert a vector-form distance vector to a square-form distance 

2239 matrix, and vice-versa. 

2240 

2241 Parameters 

2242 ---------- 

2243 X : array_like 

2244 Either a condensed or redundant distance matrix. 

2245 force : str, optional 

2246 As with MATLAB(TM), if force is equal to ``'tovector'`` or 

2247 ``'tomatrix'``, the input will be treated as a distance matrix or 

2248 distance vector respectively. 

2249 checks : bool, optional 

2250 If set to False, no checks will be made for matrix 

2251 symmetry nor zero diagonals. This is useful if it is known that 

2252 ``X - X.T1`` is small and ``diag(X)`` is close to zero. 

2253 These values are ignored any way so they do not disrupt the 

2254 squareform transformation. 

2255 

2256 Returns 

2257 ------- 

2258 Y : ndarray 

2259 If a condensed distance matrix is passed, a redundant one is 

2260 returned, or if a redundant one is passed, a condensed distance 

2261 matrix is returned. 

2262 

2263 Notes 

2264 ----- 

2265 1. ``v = squareform(X)`` 

2266 

2267 Given a square n-by-n symmetric distance matrix ``X``, 

2268 ``v = squareform(X)`` returns a ``n * (n-1) / 2`` 

2269 (i.e. binomial coefficient n choose 2) sized vector `v` 

2270 where :math:`v[{n \\choose 2} - {n-i \\choose 2} + (j-i-1)]` 

2271 is the distance between distinct points ``i`` and ``j``. 

2272 If ``X`` is non-square or asymmetric, an error is raised. 

2273 

2274 2. ``X = squareform(v)`` 

2275 

2276 Given a ``n * (n-1) / 2`` sized vector ``v`` 

2277 for some integer ``n >= 1`` encoding distances as described, 

2278 ``X = squareform(v)`` returns a n-by-n distance matrix ``X``. 

2279 The ``X[i, j]`` and ``X[j, i]`` values are set to 

2280 :math:`v[{n \\choose 2} - {n-i \\choose 2} + (j-i-1)]` 

2281 and all diagonal elements are zero. 

2282 

2283 In SciPy 0.19.0, ``squareform`` stopped casting all input types to 

2284 float64, and started returning arrays of the same dtype as the input. 

2285 

2286 Examples 

2287 -------- 

2288 >>> import numpy as np 

2289 >>> from scipy.spatial.distance import pdist, squareform 

2290 

2291 ``x`` is an array of five points in three-dimensional space. 

2292 

2293 >>> x = np.array([[2, 0, 2], [2, 2, 3], [-2, 4, 5], [0, 1, 9], [2, 2, 4]]) 

2294 

2295 ``pdist(x)`` computes the Euclidean distances between each pair of 

2296 points in ``x``. The distances are returned in a one-dimensional 

2297 array with length ``5*(5 - 1)/2 = 10``. 

2298 

2299 >>> distvec = pdist(x) 

2300 >>> distvec 

2301 array([2.23606798, 6.40312424, 7.34846923, 2.82842712, 4.89897949, 

2302 6.40312424, 1. , 5.38516481, 4.58257569, 5.47722558]) 

2303 

2304 ``squareform(distvec)`` returns the 5x5 distance matrix. 

2305 

2306 >>> m = squareform(distvec) 

2307 >>> m 

2308 array([[0. , 2.23606798, 6.40312424, 7.34846923, 2.82842712], 

2309 [2.23606798, 0. , 4.89897949, 6.40312424, 1. ], 

2310 [6.40312424, 4.89897949, 0. , 5.38516481, 4.58257569], 

2311 [7.34846923, 6.40312424, 5.38516481, 0. , 5.47722558], 

2312 [2.82842712, 1. , 4.58257569, 5.47722558, 0. ]]) 

2313 

2314 When given a square distance matrix ``m``, ``squareform(m)`` returns 

2315 the one-dimensional condensed distance vector associated with the 

2316 matrix. In this case, we recover ``distvec``. 

2317 

2318 >>> squareform(m) 

2319 array([2.23606798, 6.40312424, 7.34846923, 2.82842712, 4.89897949, 

2320 6.40312424, 1. , 5.38516481, 4.58257569, 5.47722558]) 

2321 """ 

2322 X = np.ascontiguousarray(X) 

2323 

2324 s = X.shape 

2325 

2326 if force.lower() == 'tomatrix': 

2327 if len(s) != 1: 

2328 raise ValueError("Forcing 'tomatrix' but input X is not a " 

2329 "distance vector.") 

2330 elif force.lower() == 'tovector': 

2331 if len(s) != 2: 

2332 raise ValueError("Forcing 'tovector' but input X is not a " 

2333 "distance matrix.") 

2334 

2335 # X = squareform(v) 

2336 if len(s) == 1: 

2337 if s[0] == 0: 

2338 return np.zeros((1, 1), dtype=X.dtype) 

2339 

2340 # Grab the closest value to the square root of the number 

2341 # of elements times 2 to see if the number of elements 

2342 # is indeed a binomial coefficient. 

2343 d = int(np.ceil(np.sqrt(s[0] * 2))) 

2344 

2345 # Check that v is of valid dimensions. 

2346 if d * (d - 1) != s[0] * 2: 

2347 raise ValueError('Incompatible vector size. It must be a binomial ' 

2348 'coefficient n choose 2 for some integer n >= 2.') 

2349 

2350 # Allocate memory for the distance matrix. 

2351 M = np.zeros((d, d), dtype=X.dtype) 

2352 

2353 # Since the C code does not support striding using strides. 

2354 # The dimensions are used instead. 

2355 X = _copy_array_if_base_present(X) 

2356 

2357 # Fill in the values of the distance matrix. 

2358 _distance_wrap.to_squareform_from_vector_wrap(M, X) 

2359 

2360 # Return the distance matrix. 

2361 return M 

2362 elif len(s) == 2: 

2363 if s[0] != s[1]: 

2364 raise ValueError('The matrix argument must be square.') 

2365 if checks: 

2366 is_valid_dm(X, throw=True, name='X') 

2367 

2368 # One-side of the dimensions is set here. 

2369 d = s[0] 

2370 

2371 if d <= 1: 

2372 return np.array([], dtype=X.dtype) 

2373 

2374 # Create a vector. 

2375 v = np.zeros((d * (d - 1)) // 2, dtype=X.dtype) 

2376 

2377 # Since the C code does not support striding using strides. 

2378 # The dimensions are used instead. 

2379 X = _copy_array_if_base_present(X) 

2380 

2381 # Convert the vector to squareform. 

2382 _distance_wrap.to_vector_from_squareform_wrap(X, v) 

2383 return v 

2384 else: 

2385 raise ValueError(('The first argument must be one or two dimensional ' 

2386 'array. A %d-dimensional array is not ' 

2387 'permitted') % len(s)) 

2388 

2389 

2390def is_valid_dm(D, tol=0.0, throw=False, name="D", warning=False): 

2391 """ 

2392 Return True if input array is a valid distance matrix. 

2393 

2394 Distance matrices must be 2-dimensional numpy arrays. 

2395 They must have a zero-diagonal, and they must be symmetric. 

2396 

2397 Parameters 

2398 ---------- 

2399 D : array_like 

2400 The candidate object to test for validity. 

2401 tol : float, optional 

2402 The distance matrix should be symmetric. `tol` is the maximum 

2403 difference between entries ``ij`` and ``ji`` for the distance 

2404 metric to be considered symmetric. 

2405 throw : bool, optional 

2406 An exception is thrown if the distance matrix passed is not valid. 

2407 name : str, optional 

2408 The name of the variable to checked. This is useful if 

2409 throw is set to True so the offending variable can be identified 

2410 in the exception message when an exception is thrown. 

2411 warning : bool, optional 

2412 Instead of throwing an exception, a warning message is 

2413 raised. 

2414 

2415 Returns 

2416 ------- 

2417 valid : bool 

2418 True if the variable `D` passed is a valid distance matrix. 

2419 

2420 Notes 

2421 ----- 

2422 Small numerical differences in `D` and `D.T` and non-zeroness of 

2423 the diagonal are ignored if they are within the tolerance specified 

2424 by `tol`. 

2425 

2426 Examples 

2427 -------- 

2428 >>> import numpy as np 

2429 >>> from scipy.spatial.distance import is_valid_dm 

2430 

2431 This matrix is a valid distance matrix. 

2432 

2433 >>> d = np.array([[0.0, 1.1, 1.2, 1.3], 

2434 ... [1.1, 0.0, 1.0, 1.4], 

2435 ... [1.2, 1.0, 0.0, 1.5], 

2436 ... [1.3, 1.4, 1.5, 0.0]]) 

2437 >>> is_valid_dm(d) 

2438 True 

2439 

2440 In the following examples, the input is not a valid distance matrix. 

2441 

2442 Not square: 

2443 

2444 >>> is_valid_dm([[0, 2, 2], [2, 0, 2]]) 

2445 False 

2446 

2447 Nonzero diagonal element: 

2448 

2449 >>> is_valid_dm([[0, 1, 1], [1, 2, 3], [1, 3, 0]]) 

2450 False 

2451 

2452 Not symmetric: 

2453 

2454 >>> is_valid_dm([[0, 1, 3], [2, 0, 1], [3, 1, 0]]) 

2455 False 

2456 

2457 """ 

2458 D = np.asarray(D, order='c') 

2459 valid = True 

2460 try: 

2461 s = D.shape 

2462 if len(D.shape) != 2: 

2463 if name: 

2464 raise ValueError(('Distance matrix \'%s\' must have shape=2 ' 

2465 '(i.e. be two-dimensional).') % name) 

2466 else: 

2467 raise ValueError('Distance matrix must have shape=2 (i.e. ' 

2468 'be two-dimensional).') 

2469 if tol == 0.0: 

2470 if not (D == D.T).all(): 

2471 if name: 

2472 raise ValueError(('Distance matrix \'%s\' must be ' 

2473 'symmetric.') % name) 

2474 else: 

2475 raise ValueError('Distance matrix must be symmetric.') 

2476 if not (D[range(0, s[0]), range(0, s[0])] == 0).all(): 

2477 if name: 

2478 raise ValueError(('Distance matrix \'%s\' diagonal must ' 

2479 'be zero.') % name) 

2480 else: 

2481 raise ValueError('Distance matrix diagonal must be zero.') 

2482 else: 

2483 if not (D - D.T <= tol).all(): 

2484 if name: 

2485 raise ValueError(('Distance matrix \'%s\' must be ' 

2486 'symmetric within tolerance %5.5f.') 

2487 % (name, tol)) 

2488 else: 

2489 raise ValueError('Distance matrix must be symmetric within' 

2490 ' tolerance %5.5f.' % tol) 

2491 if not (D[range(0, s[0]), range(0, s[0])] <= tol).all(): 

2492 if name: 

2493 raise ValueError(('Distance matrix \'%s\' diagonal must be' 

2494 ' close to zero within tolerance %5.5f.') 

2495 % (name, tol)) 

2496 else: 

2497 raise ValueError(('Distance matrix \'%s\' diagonal must be' 

2498 ' close to zero within tolerance %5.5f.') 

2499 % tol) 

2500 except Exception as e: 

2501 if throw: 

2502 raise 

2503 if warning: 

2504 warnings.warn(str(e)) 

2505 valid = False 

2506 return valid 

2507 

2508 

2509def is_valid_y(y, warning=False, throw=False, name=None): 

2510 """ 

2511 Return True if the input array is a valid condensed distance matrix. 

2512 

2513 Condensed distance matrices must be 1-dimensional numpy arrays. 

2514 Their length must be a binomial coefficient :math:`{n \\choose 2}` 

2515 for some positive integer n. 

2516 

2517 Parameters 

2518 ---------- 

2519 y : array_like 

2520 The condensed distance matrix. 

2521 warning : bool, optional 

2522 Invokes a warning if the variable passed is not a valid 

2523 condensed distance matrix. The warning message explains why 

2524 the distance matrix is not valid. `name` is used when 

2525 referencing the offending variable. 

2526 throw : bool, optional 

2527 Throws an exception if the variable passed is not a valid 

2528 condensed distance matrix. 

2529 name : bool, optional 

2530 Used when referencing the offending variable in the 

2531 warning or exception message. 

2532 

2533 Returns 

2534 ------- 

2535 bool 

2536 True if the input array is a valid condensed distance matrix, 

2537 False otherwise. 

2538 

2539 Examples 

2540 -------- 

2541 >>> from scipy.spatial.distance import is_valid_y 

2542 

2543 This vector is a valid condensed distance matrix. The length is 6, 

2544 which corresponds to ``n = 4``, since ``4*(4 - 1)/2`` is 6. 

2545 

2546 >>> v = [1.0, 1.2, 1.0, 0.5, 1.3, 0.9] 

2547 >>> is_valid_y(v) 

2548 True 

2549 

2550 An input vector with length, say, 7, is not a valid condensed distance 

2551 matrix. 

2552 

2553 >>> is_valid_y([1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7]) 

2554 False 

2555 

2556 """ 

2557 y = np.asarray(y, order='c') 

2558 valid = True 

2559 try: 

2560 if len(y.shape) != 1: 

2561 if name: 

2562 raise ValueError(('Condensed distance matrix \'%s\' must ' 

2563 'have shape=1 (i.e. be one-dimensional).') 

2564 % name) 

2565 else: 

2566 raise ValueError('Condensed distance matrix must have shape=1 ' 

2567 '(i.e. be one-dimensional).') 

2568 n = y.shape[0] 

2569 d = int(np.ceil(np.sqrt(n * 2))) 

2570 if (d * (d - 1) / 2) != n: 

2571 if name: 

2572 raise ValueError(('Length n of condensed distance matrix ' 

2573 '\'%s\' must be a binomial coefficient, i.e.' 

2574 'there must be a k such that ' 

2575 '(k \\choose 2)=n)!') % name) 

2576 else: 

2577 raise ValueError('Length n of condensed distance matrix must ' 

2578 'be a binomial coefficient, i.e. there must ' 

2579 'be a k such that (k \\choose 2)=n)!') 

2580 except Exception as e: 

2581 if throw: 

2582 raise 

2583 if warning: 

2584 warnings.warn(str(e)) 

2585 valid = False 

2586 return valid 

2587 

2588 

2589def num_obs_dm(d): 

2590 """ 

2591 Return the number of original observations that correspond to a 

2592 square, redundant distance matrix. 

2593 

2594 Parameters 

2595 ---------- 

2596 d : array_like 

2597 The target distance matrix. 

2598 

2599 Returns 

2600 ------- 

2601 num_obs_dm : int 

2602 The number of observations in the redundant distance matrix. 

2603 

2604 """ 

2605 d = np.asarray(d, order='c') 

2606 is_valid_dm(d, tol=np.inf, throw=True, name='d') 

2607 return d.shape[0] 

2608 

2609 

2610def num_obs_y(Y): 

2611 """ 

2612 Return the number of original observations that correspond to a 

2613 condensed distance matrix. 

2614 

2615 Parameters 

2616 ---------- 

2617 Y : array_like 

2618 Condensed distance matrix. 

2619 

2620 Returns 

2621 ------- 

2622 n : int 

2623 The number of observations in the condensed distance matrix `Y`. 

2624 

2625 """ 

2626 Y = np.asarray(Y, order='c') 

2627 is_valid_y(Y, throw=True, name='Y') 

2628 k = Y.shape[0] 

2629 if k == 0: 

2630 raise ValueError("The number of observations cannot be determined on " 

2631 "an empty distance matrix.") 

2632 d = int(np.ceil(np.sqrt(k * 2))) 

2633 if (d * (d - 1) / 2) != k: 

2634 raise ValueError("Invalid condensed distance matrix passed. Must be " 

2635 "some k where k=(n choose 2) for some n >= 2.") 

2636 return d 

2637 

2638 

2639def _prepare_out_argument(out, dtype, expected_shape): 

2640 if out is None: 

2641 return np.empty(expected_shape, dtype=dtype) 

2642 

2643 if out.shape != expected_shape: 

2644 raise ValueError("Output array has incorrect shape.") 

2645 if not out.flags.c_contiguous: 

2646 raise ValueError("Output array must be C-contiguous.") 

2647 if out.dtype != np.double: 

2648 raise ValueError("Output array must be double type.") 

2649 return out 

2650 

2651 

2652def _pdist_callable(X, *, out, metric, **kwargs): 

2653 n = X.shape[0] 

2654 out_size = (n * (n - 1)) // 2 

2655 dm = _prepare_out_argument(out, np.double, (out_size,)) 

2656 k = 0 

2657 for i in range(X.shape[0] - 1): 

2658 for j in range(i + 1, X.shape[0]): 

2659 dm[k] = metric(X[i], X[j], **kwargs) 

2660 k += 1 

2661 return dm 

2662 

2663 

2664def _cdist_callable(XA, XB, *, out, metric, **kwargs): 

2665 mA = XA.shape[0] 

2666 mB = XB.shape[0] 

2667 dm = _prepare_out_argument(out, np.double, (mA, mB)) 

2668 for i in range(mA): 

2669 for j in range(mB): 

2670 dm[i, j] = metric(XA[i], XB[j], **kwargs) 

2671 return dm 

2672 

2673 

2674def cdist(XA, XB, metric='euclidean', *, out=None, **kwargs): 

2675 """ 

2676 Compute distance between each pair of the two collections of inputs. 

2677 

2678 See Notes for common calling conventions. 

2679 

2680 Parameters 

2681 ---------- 

2682 XA : array_like 

2683 An :math:`m_A` by :math:`n` array of :math:`m_A` 

2684 original observations in an :math:`n`-dimensional space. 

2685 Inputs are converted to float type. 

2686 XB : array_like 

2687 An :math:`m_B` by :math:`n` array of :math:`m_B` 

2688 original observations in an :math:`n`-dimensional space. 

2689 Inputs are converted to float type. 

2690 metric : str or callable, optional 

2691 The distance metric to use. If a string, the distance function can be 

2692 'braycurtis', 'canberra', 'chebyshev', 'cityblock', 'correlation', 

2693 'cosine', 'dice', 'euclidean', 'hamming', 'jaccard', 'jensenshannon', 

2694 'kulczynski1', 'mahalanobis', 'matching', 'minkowski', 

2695 'rogerstanimoto', 'russellrao', 'seuclidean', 'sokalmichener', 

2696 'sokalsneath', 'sqeuclidean', 'yule'. 

2697 **kwargs : dict, optional 

2698 Extra arguments to `metric`: refer to each metric documentation for a 

2699 list of all possible arguments. 

2700 

2701 Some possible arguments: 

2702 

2703 p : scalar 

2704 The p-norm to apply for Minkowski, weighted and unweighted. 

2705 Default: 2. 

2706 

2707 w : array_like 

2708 The weight vector for metrics that support weights (e.g., Minkowski). 

2709 

2710 V : array_like 

2711 The variance vector for standardized Euclidean. 

2712 Default: var(vstack([XA, XB]), axis=0, ddof=1) 

2713 

2714 VI : array_like 

2715 The inverse of the covariance matrix for Mahalanobis. 

2716 Default: inv(cov(vstack([XA, XB].T))).T 

2717 

2718 out : ndarray 

2719 The output array 

2720 If not None, the distance matrix Y is stored in this array. 

2721 

2722 Returns 

2723 ------- 

2724 Y : ndarray 

2725 A :math:`m_A` by :math:`m_B` distance matrix is returned. 

2726 For each :math:`i` and :math:`j`, the metric 

2727 ``dist(u=XA[i], v=XB[j])`` is computed and stored in the 

2728 :math:`ij` th entry. 

2729 

2730 Raises 

2731 ------ 

2732 ValueError 

2733 An exception is thrown if `XA` and `XB` do not have 

2734 the same number of columns. 

2735 

2736 Notes 

2737 ----- 

2738 The following are common calling conventions: 

2739 

2740 1. ``Y = cdist(XA, XB, 'euclidean')`` 

2741 

2742 Computes the distance between :math:`m` points using 

2743 Euclidean distance (2-norm) as the distance metric between the 

2744 points. The points are arranged as :math:`m` 

2745 :math:`n`-dimensional row vectors in the matrix X. 

2746 

2747 2. ``Y = cdist(XA, XB, 'minkowski', p=2.)`` 

2748 

2749 Computes the distances using the Minkowski distance 

2750 :math:`\\|u-v\\|_p` (:math:`p`-norm) where :math:`p > 0` (note 

2751 that this is only a quasi-metric if :math:`0 < p < 1`). 

2752 

2753 3. ``Y = cdist(XA, XB, 'cityblock')`` 

2754 

2755 Computes the city block or Manhattan distance between the 

2756 points. 

2757 

2758 4. ``Y = cdist(XA, XB, 'seuclidean', V=None)`` 

2759 

2760 Computes the standardized Euclidean distance. The standardized 

2761 Euclidean distance between two n-vectors ``u`` and ``v`` is 

2762 

2763 .. math:: 

2764 

2765 \\sqrt{\\sum {(u_i-v_i)^2 / V[x_i]}}. 

2766 

2767 V is the variance vector; V[i] is the variance computed over all 

2768 the i'th components of the points. If not passed, it is 

2769 automatically computed. 

2770 

2771 5. ``Y = cdist(XA, XB, 'sqeuclidean')`` 

2772 

2773 Computes the squared Euclidean distance :math:`\\|u-v\\|_2^2` between 

2774 the vectors. 

2775 

2776 6. ``Y = cdist(XA, XB, 'cosine')`` 

2777 

2778 Computes the cosine distance between vectors u and v, 

2779 

2780 .. math:: 

2781 

2782 1 - \\frac{u \\cdot v} 

2783 {{\\|u\\|}_2 {\\|v\\|}_2} 

2784 

2785 where :math:`\\|*\\|_2` is the 2-norm of its argument ``*``, and 

2786 :math:`u \\cdot v` is the dot product of :math:`u` and :math:`v`. 

2787 

2788 7. ``Y = cdist(XA, XB, 'correlation')`` 

2789 

2790 Computes the correlation distance between vectors u and v. This is 

2791 

2792 .. math:: 

2793 

2794 1 - \\frac{(u - \\bar{u}) \\cdot (v - \\bar{v})} 

2795 {{\\|(u - \\bar{u})\\|}_2 {\\|(v - \\bar{v})\\|}_2} 

2796 

2797 where :math:`\\bar{v}` is the mean of the elements of vector v, 

2798 and :math:`x \\cdot y` is the dot product of :math:`x` and :math:`y`. 

2799 

2800 

2801 8. ``Y = cdist(XA, XB, 'hamming')`` 

2802 

2803 Computes the normalized Hamming distance, or the proportion of 

2804 those vector elements between two n-vectors ``u`` and ``v`` 

2805 which disagree. To save memory, the matrix ``X`` can be of type 

2806 boolean. 

2807 

2808 9. ``Y = cdist(XA, XB, 'jaccard')`` 

2809 

2810 Computes the Jaccard distance between the points. Given two 

2811 vectors, ``u`` and ``v``, the Jaccard distance is the 

2812 proportion of those elements ``u[i]`` and ``v[i]`` that 

2813 disagree where at least one of them is non-zero. 

2814 

2815 10. ``Y = cdist(XA, XB, 'jensenshannon')`` 

2816 

2817 Computes the Jensen-Shannon distance between two probability arrays. 

2818 Given two probability vectors, :math:`p` and :math:`q`, the 

2819 Jensen-Shannon distance is 

2820 

2821 .. math:: 

2822 

2823 \\sqrt{\\frac{D(p \\parallel m) + D(q \\parallel m)}{2}} 

2824 

2825 where :math:`m` is the pointwise mean of :math:`p` and :math:`q` 

2826 and :math:`D` is the Kullback-Leibler divergence. 

2827 

2828 11. ``Y = cdist(XA, XB, 'chebyshev')`` 

2829 

2830 Computes the Chebyshev distance between the points. The 

2831 Chebyshev distance between two n-vectors ``u`` and ``v`` is the 

2832 maximum norm-1 distance between their respective elements. More 

2833 precisely, the distance is given by 

2834 

2835 .. math:: 

2836 

2837 d(u,v) = \\max_i {|u_i-v_i|}. 

2838 

2839 12. ``Y = cdist(XA, XB, 'canberra')`` 

2840 

2841 Computes the Canberra distance between the points. The 

2842 Canberra distance between two points ``u`` and ``v`` is 

2843 

2844 .. math:: 

2845 

2846 d(u,v) = \\sum_i \\frac{|u_i-v_i|} 

2847 {|u_i|+|v_i|}. 

2848 

2849 13. ``Y = cdist(XA, XB, 'braycurtis')`` 

2850 

2851 Computes the Bray-Curtis distance between the points. The 

2852 Bray-Curtis distance between two points ``u`` and ``v`` is 

2853 

2854 

2855 .. math:: 

2856 

2857 d(u,v) = \\frac{\\sum_i (|u_i-v_i|)} 

2858 {\\sum_i (|u_i+v_i|)} 

2859 

2860 14. ``Y = cdist(XA, XB, 'mahalanobis', VI=None)`` 

2861 

2862 Computes the Mahalanobis distance between the points. The 

2863 Mahalanobis distance between two points ``u`` and ``v`` is 

2864 :math:`\\sqrt{(u-v)(1/V)(u-v)^T}` where :math:`(1/V)` (the ``VI`` 

2865 variable) is the inverse covariance. If ``VI`` is not None, 

2866 ``VI`` will be used as the inverse covariance matrix. 

2867 

2868 15. ``Y = cdist(XA, XB, 'yule')`` 

2869 

2870 Computes the Yule distance between the boolean 

2871 vectors. (see `yule` function documentation) 

2872 

2873 16. ``Y = cdist(XA, XB, 'matching')`` 

2874 

2875 Synonym for 'hamming'. 

2876 

2877 17. ``Y = cdist(XA, XB, 'dice')`` 

2878 

2879 Computes the Dice distance between the boolean vectors. (see 

2880 `dice` function documentation) 

2881 

2882 18. ``Y = cdist(XA, XB, 'kulczynski1')`` 

2883 

2884 Computes the kulczynski distance between the boolean 

2885 vectors. (see `kulczynski1` function documentation) 

2886 

2887 19. ``Y = cdist(XA, XB, 'rogerstanimoto')`` 

2888 

2889 Computes the Rogers-Tanimoto distance between the boolean 

2890 vectors. (see `rogerstanimoto` function documentation) 

2891 

2892 20. ``Y = cdist(XA, XB, 'russellrao')`` 

2893 

2894 Computes the Russell-Rao distance between the boolean 

2895 vectors. (see `russellrao` function documentation) 

2896 

2897 21. ``Y = cdist(XA, XB, 'sokalmichener')`` 

2898 

2899 Computes the Sokal-Michener distance between the boolean 

2900 vectors. (see `sokalmichener` function documentation) 

2901 

2902 22. ``Y = cdist(XA, XB, 'sokalsneath')`` 

2903 

2904 Computes the Sokal-Sneath distance between the vectors. (see 

2905 `sokalsneath` function documentation) 

2906 

2907 23. ``Y = cdist(XA, XB, f)`` 

2908 

2909 Computes the distance between all pairs of vectors in X 

2910 using the user supplied 2-arity function f. For example, 

2911 Euclidean distance between the vectors could be computed 

2912 as follows:: 

2913 

2914 dm = cdist(XA, XB, lambda u, v: np.sqrt(((u-v)**2).sum())) 

2915 

2916 Note that you should avoid passing a reference to one of 

2917 the distance functions defined in this library. For example,:: 

2918 

2919 dm = cdist(XA, XB, sokalsneath) 

2920 

2921 would calculate the pair-wise distances between the vectors in 

2922 X using the Python function `sokalsneath`. This would result in 

2923 sokalsneath being called :math:`{n \\choose 2}` times, which 

2924 is inefficient. Instead, the optimized C version is more 

2925 efficient, and we call it using the following syntax:: 

2926 

2927 dm = cdist(XA, XB, 'sokalsneath') 

2928 

2929 Examples 

2930 -------- 

2931 Find the Euclidean distances between four 2-D coordinates: 

2932 

2933 >>> from scipy.spatial import distance 

2934 >>> import numpy as np 

2935 >>> coords = [(35.0456, -85.2672), 

2936 ... (35.1174, -89.9711), 

2937 ... (35.9728, -83.9422), 

2938 ... (36.1667, -86.7833)] 

2939 >>> distance.cdist(coords, coords, 'euclidean') 

2940 array([[ 0. , 4.7044, 1.6172, 1.8856], 

2941 [ 4.7044, 0. , 6.0893, 3.3561], 

2942 [ 1.6172, 6.0893, 0. , 2.8477], 

2943 [ 1.8856, 3.3561, 2.8477, 0. ]]) 

2944 

2945 

2946 Find the Manhattan distance from a 3-D point to the corners of the unit 

2947 cube: 

2948 

2949 >>> a = np.array([[0, 0, 0], 

2950 ... [0, 0, 1], 

2951 ... [0, 1, 0], 

2952 ... [0, 1, 1], 

2953 ... [1, 0, 0], 

2954 ... [1, 0, 1], 

2955 ... [1, 1, 0], 

2956 ... [1, 1, 1]]) 

2957 >>> b = np.array([[ 0.1, 0.2, 0.4]]) 

2958 >>> distance.cdist(a, b, 'cityblock') 

2959 array([[ 0.7], 

2960 [ 0.9], 

2961 [ 1.3], 

2962 [ 1.5], 

2963 [ 1.5], 

2964 [ 1.7], 

2965 [ 2.1], 

2966 [ 2.3]]) 

2967 

2968 """ 

2969 # You can also call this as: 

2970 # Y = cdist(XA, XB, 'test_abc') 

2971 # where 'abc' is the metric being tested. This computes the distance 

2972 # between all pairs of vectors in XA and XB using the distance metric 'abc' 

2973 # but with a more succinct, verifiable, but less efficient implementation. 

2974 

2975 XA = np.asarray(XA) 

2976 XB = np.asarray(XB) 

2977 

2978 s = XA.shape 

2979 sB = XB.shape 

2980 

2981 if len(s) != 2: 

2982 raise ValueError('XA must be a 2-dimensional array.') 

2983 if len(sB) != 2: 

2984 raise ValueError('XB must be a 2-dimensional array.') 

2985 if s[1] != sB[1]: 

2986 raise ValueError('XA and XB must have the same number of columns ' 

2987 '(i.e. feature dimension.)') 

2988 

2989 mA = s[0] 

2990 mB = sB[0] 

2991 n = s[1] 

2992 

2993 if callable(metric): 

2994 mstr = getattr(metric, '__name__', 'Unknown') 

2995 metric_info = _METRIC_ALIAS.get(mstr, None) 

2996 if metric_info is not None: 

2997 XA, XB, typ, kwargs = _validate_cdist_input( 

2998 XA, XB, mA, mB, n, metric_info, **kwargs) 

2999 return _cdist_callable(XA, XB, metric=metric, out=out, **kwargs) 

3000 elif isinstance(metric, str): 

3001 mstr = metric.lower() 

3002 metric_info = _METRIC_ALIAS.get(mstr, None) 

3003 if metric_info is not None: 

3004 cdist_fn = metric_info.cdist_func 

3005 _extra_windows_error_checks(XA, out, (mA, mB), **kwargs) 

3006 return cdist_fn(XA, XB, out=out, **kwargs) 

3007 elif mstr.startswith("test_"): 

3008 metric_info = _TEST_METRICS.get(mstr, None) 

3009 if metric_info is None: 

3010 raise ValueError(f'Unknown "Test" Distance Metric: {mstr[5:]}') 

3011 XA, XB, typ, kwargs = _validate_cdist_input( 

3012 XA, XB, mA, mB, n, metric_info, **kwargs) 

3013 return _cdist_callable( 

3014 XA, XB, metric=metric_info.dist_func, out=out, **kwargs) 

3015 else: 

3016 raise ValueError('Unknown Distance Metric: %s' % mstr) 

3017 else: 

3018 raise TypeError('2nd argument metric must be a string identifier ' 

3019 'or a function.')