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)
| 478 | return result |
| 479 | |
| 480 | def choices(self, population, weights=None, *, cum_weights=None, k=1): |
| 481 | """Return a k sized list of population elements chosen with replacement. |
| 482 | |
| 483 | If the relative weights or cumulative weights are not specified, |
| 484 | the selections are made with equal probability. |
| 485 | |
| 486 | """ |
| 487 | random = self.random |
| 488 | n = len(population) |
| 489 | if cum_weights is None: |
| 490 | if weights is None: |
| 491 | floor = _floor |
| 492 | n += 0.0 # convert to float for a small speed improvement |
| 493 | return [population[floor(random() * n)] for i in _repeat(None, k)] |
| 494 | try: |
| 495 | cum_weights = list(_accumulate(weights)) |
| 496 | except TypeError: |
| 497 | if not isinstance(weights, int): |
| 498 | raise |
| 499 | k = weights |
| 500 | raise TypeError( |
| 501 | f'The number of choices must be a keyword argument: {k=}' |
| 502 | ) from None |
| 503 | elif weights is not None: |
| 504 | raise TypeError('Cannot specify both weights and cumulative weights') |
| 505 | if len(cum_weights) != n: |
| 506 | raise ValueError('The number of weights does not match the population') |
| 507 | total = cum_weights[-1] + 0.0 # convert to float |
| 508 | if total <= 0.0: |
| 509 | raise ValueError('Total of weights must be greater than zero') |
| 510 | if not _isfinite(total): |
| 511 | raise ValueError('Total of weights must be finite') |
| 512 | bisect = _bisect |
| 513 | hi = n - 1 |
| 514 | return [population[bisect(cum_weights, random() * total, 0, hi)] |
| 515 | for i in _repeat(None, k)] |
| 516 | |
| 517 | |
| 518 | ## -------------------- real-valued distributions ------------------- |