Gerar matriz aleatória de flutuadores entre um intervalo

88

Não consegui encontrar uma função para gerar uma matriz de flutuadores aleatórios de um determinado comprimento entre um determinado intervalo.

Eu olhei para Amostragem aleatória, mas nenhuma função parece fazer o que eu preciso.

random.uniform chega perto, mas retorna apenas um único elemento, não um número específico.

Isso é o que eu procuro:

ran_floats = some_function(low=0.5, high=13.3, size=50)

que retornaria uma matriz de 50 flutuadores aleatórios não exclusivos (isto é: repetições são permitidas) uniformemente distribuídas no intervalo [0.5, 13.3].

Existe tal função?

Gabriel
fonte
5
Você marcou a pergunta numpy, mas não a mencionou numpy.random.uniform, embora ela tenha exatamente a assinatura de chamada desejada. Você tem a numpybiblioteca disponível?
DSM de
1
[random.uniform(low, high) for i in xrange(size)]
Filogênese
1
@DSM sim, e você está aparentemente 100% correto. Perdi essa função e parece fazer exatamente o que preciso. Você se importaria de apresentar seu comentário como uma resposta?
Gabriel

Respostas:

135

np.random.uniform se encaixa no seu caso de uso:

sampl = np.random.uniform(low=0.5, high=13.3, size=(50,))

Atualização em outubro de 2019:

Embora a sintaxe ainda seja compatível, parece que a API mudou com o NumPy 1.17 para oferecer suporte a maior controle sobre o gerador de números aleatórios. Daqui para frente, a API mudou e você deve olhar em https://docs.scipy.org/doc/numpy/reference/random/generated/numpy.random.Generator.uniform.html

A proposta de aprimoramento está aqui: https://numpy.org/neps/nep-0019-rng-policy.html

JoshAdel
fonte
23
A pergunta de pesquisa intuitiva do OP é some_function(low=0.5, high=13.3, size=50). É assim que as libs python são projetadas #wow
Saravanabalagi Ramachandran
O tamanho não estava totalmente claro e o link não funciona. Aqui está um pequeno esclarecimento. size: int ou tupla de ints, opcional. Forma de saída. Se a forma fornecida for, por exemplo, (m, n, k), então m * n * k amostras são retiradas. Se o tamanho for nenhum padrão), um único valor será retornado se baixo e alto forem ambos escalares.
vlad
@vlad - obrigado por apontar o problema com o link. Eu atualizei a resposta para cobrir o uso atual.
JoshAdel
20

Por que não usar uma compreensão de lista?

Em Python 2

ran_floats = [random.uniform(low,high) for _ in xrange(size)]

Em Python 3, rangefunciona como xrange( ref )

ran_floats = [random.uniform(low,high) for _ in range(size)]
Isedev
fonte
3

Por que não combinar random.uniform com uma compreensão de lista?

>>> def random_floats(low, high, size):
...    return [random.uniform(low, high) for _ in xrange(size)]
... 
>>> random_floats(0.5, 2.8, 5)
[2.366910411506704, 1.878800401620107, 1.0145196974227986, 2.332600336488709, 1.945869474662082]
pkacprzak
fonte
3

Pode já haver uma função para fazer o que você está procurando, mas eu não sei (ainda?). Nesse ínterim, sugiro usar:

ran_floats = numpy.random.rand(50) * (13.3-0.5) + 0.5

Isso produzirá uma matriz de forma (50,) com uma distribuição uniforme entre 0,5 e 13,3.

Você também pode definir uma função:

def random_uniform_range(shape=[1,],low=0,high=1):
    """
    Random uniform range

    Produces a random uniform distribution of specified shape, with arbitrary max and
    min values. Default shape is [1], and default range is [0,1].
    """
    return numpy.random.rand(shape) * (high - min) + min

EDIT : Hmm, sim, então eu perdi, há numpy.random.uniform () com a mesma chamada exata que você deseja! Tente import numpy; help(numpy.random.uniform)obter mais informações.

PhilMacKay
fonte
3

O loop for na compreensão da lista leva tempo e o torna lento. É melhor usar parâmetros numpy (baixo, alto, tamanho, ..etc)

import numpy as np
import time
rang = 10000
tic = time.time()
for i in range(rang):
    sampl = np.random.uniform(low=0, high=2, size=(182))
print("it took: ", time.time() - tic)

tic = time.time()
for i in range(rang):
    ran_floats = [np.random.uniform(0,2) for _ in range(182)]
print("it took: ", time.time() - tic)

saída de amostra:

('levou:', 0,06406784057617188)

('levou:', 1,7253198623657227)

Mohamed Ibrahim
fonte
3

Alternativamente, você pode usar SciPy

from scipy import stats
stats.uniform(0.5, 13.3).rvs(50)

e para o registro de amostras inteiras é

stats.randint(10, 20).rvs(50)
Stuart Hallows
fonte
2

Esta é a maneira mais simples

np.random.uniform(start,stop,(rows,columns))
George Gee
fonte
0

np.random.random_sample(size) irá gerar flutuações aleatórias no intervalo semiaberto [0,0, 1,0).

Shivaraj Karki
fonte