Return a k sized list of population elements chosen with replacement. If the relative weights or cumulative weights are not specified, the selections are made with equal probability.
(self, population, weights=None, *, cum_weights=None, k=1)
| 458 | return result |
| 459 | |
| 460 | def choices(self, population, weights=None, *, cum_weights=None, k=1): |
| 461 | """Return a k sized list of population elements chosen with replacement. |
| 462 | |
| 463 | If the relative weights or cumulative weights are not specified, |
| 464 | the selections are made with equal probability. |
| 465 | |
| 466 | """ |
| 467 | random = self.random |
| 468 | n = len(population) |
| 469 | if cum_weights is None: |
| 470 | if weights is None: |
| 471 | floor = _floor |
| 472 | n += 0.0 # convert to float for a small speed improvement |
| 473 | return [population[floor(random() * n)] for i in _repeat(None, k)] |
| 474 | try: |
| 475 | cum_weights = list(_accumulate(weights)) |
| 476 | except TypeError: |
| 477 | if not isinstance(weights, int): |
| 478 | raise |
| 479 | k = weights |
| 480 | raise TypeError( |
| 481 | f'The number of choices must be a keyword argument: {k=}' |
| 482 | ) from None |
| 483 | elif weights is not None: |
| 484 | raise TypeError('Cannot specify both weights and cumulative weights') |
| 485 | if len(cum_weights) != n: |
| 486 | raise ValueError('The number of weights does not match the population') |
| 487 | total = cum_weights[-1] + 0.0 # convert to float |
| 488 | if total <= 0.0: |
| 489 | raise ValueError('Total of weights must be greater than zero') |
| 490 | if not _isfinite(total): |
| 491 | raise ValueError('Total of weights must be finite') |
| 492 | bisect = _bisect |
| 493 | hi = n - 1 |
| 494 | return [population[bisect(cum_weights, random() * total, 0, hi)] |
| 495 | for i in _repeat(None, k)] |
| 496 | |
| 497 | |
| 498 | ## -------------------- real-valued distributions ------------------- |