14

l have a vector of random numbers that l want to permute randomly using randperm() function as follows but it's not working.

X=rand(100000) # a vector of 100000 random elements
Y=randperm(X) # want to permute randomly the vector x

the returned error is : ERROR: MethodError: no method matching randperm(::Array{Float64,1}) in eval(::Module, ::Any) at ./boot.jl:237

Thank you

Stuart
  • 1,322
  • 1
  • 13
  • 31
vincet
  • 917
  • 3
  • 13
  • 26
  • because randperm() is also used in matlab and julia language is a trade-off between matlab and python. actually the function is the same but l don't know why it's not working – vincet Jun 24 '16 at 09:39

2 Answers2

20

Use shuffle()

If your only goal is to randomly permute the vector, you can use shuffle() (part of the Random module):

julia> using Random;

julia> X = collect(1:5)
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

julia> shuffle(X)
5-element Array{Int64,1}:
 5
 4
 1
 2
 3

If you don't want to allocate a new vector, but want to shuffle in place, you can use shuffle!():

julia> shuffle!(X);

julia> X
5-element Vector{Int64}:
 3
 4
 2
 5
 1

randperm()

randperm() accepts an integer n and gives a permutation of length n. You can use this ordering to then reorder your original vector:

julia> X[randperm(length(X))]
5-element Array{Int64,1}:
 3
 4
 1
 2
 5

Bonus: Sampling without replacement

You can also use StatsBase.sample() to sample the same length(X) elements from your array without replacement:

julia> import StatsBase;

julia> StatsBase.sample(X, length(X), replace=false)
5-element Vector{Int64}:
 5
 2
 4
 1
 3
niczky12
  • 4,953
  • 1
  • 24
  • 34
2

To piggyback on the second point in the answer by @niczky12, if you want to randomly permute the vector X directly then it is actually more efficient to call shuffle!(X) instead of shuffle(X):

# precompile @time
@time 1+1

# create random vector
p = 10_000
X = collect(1:p)

# reproducible shuffles
srand(2016)

shuffle(X)
@time shuffle(X)

shuffle!(X)
@time shuffle!(X)

Output on my machine:

  0.000004 seconds (148 allocations: 10.151 KB)
  0.000331 seconds (6 allocations: 78.344 KB)
  0.000309 seconds (4 allocations: 160 bytes)

The call to shuffle! allocates substantially less memory (160 bytes v. 78 Kb) and thus will scale better with p.

Kevin L. Keys
  • 997
  • 8
  • 21
  • 2
    Don't use global variables when benchmarking, wrap everything in a function. You can also use the BenchmarkTools package – David P. Sanders Jun 25 '16 at 18:38
  • Oh, maybe it doesn't matter here though – David P. Sanders Jun 25 '16 at 18:39
  • It shouldn't matter here since I sought to compare memory allocations and not compute times. It is good Julia coding practice to wrap everything in functions. On my machine, wrapping the script in a function does not change the result. – Kevin L. Keys Jun 25 '16 at 19:32