Julia, convert selected elements of an array to a new number with binomial frequency

163 Views Asked by At

I'm attempting to independently select elements of an array that meet a condition and then convert those elements to a different value, with a given frequency. In R I'd use rbinom, but can't find the correct function in Julia. MWE:

#create array
a = [3,4,3,6,3];

# convert elements that match ==3 to 9
a[a .==3] .=9;

a
[9,4,9,6,9]

but what I can't figure out how to do is the conversion with binomial probability (might be bernoulli?) of, for example, 0.66 so converted a might end up as

[3,4,9,6,9]

I think what I want is something like:

a[a .==3] .= bernoulli(0.66)9

Such that the probability of being converted from 3 to 9 is 0.66. So 66% of the time it will convert the 3 to 9, and the remaining 33% it will just leave it as a 3. Make sense?

I'd like to do the evaluation independently on each instance of 3, rather than extracting an index vector of all the 3's and then calculating how many are converted with a probability (if that makes any sense?!) Thx J

1

There are 1 best solutions below

0
On

I don't know any pre-made solution here (I'm not familiar with the field really), but you can roll your own solution easily.

I think you should be using a Bernoulli distribution actually, unless I'm mistaken. You can either use Bernoulli from Distributions.jl, or you can make your own with plain old rand:

using Distributions: Bernoulli

function rbinom!(xs, subst::Pair, p=1.0)
    (x, y) = subst
    dist = Bernoulli(p)
    for (i, val) in pairs(xs)
        if val == x && rand(dist)
            xs[i] = y
        end
    end
    return xs
end

If you don't want to import Distributions.jl, you can just write

function rbinom!(xs, subst::Pair, p=1.0)
    (x, y) = subst
    for (i, val) in pairs(xs)
        if val == x && rand() < p  # or rand() <= p ?
            xs[i] = y
        end
    end
    return xs
end

You call it like this:

julia> a = [3,4,3,6,3];

julia> rbinom!(a, 3=>9, 0.66)
5-element Array{Int64,1}:
 9
 4
 9
 6
 3

Note that this function updates the vector a in-place. If you don't want that you can create a wrapper function that sends in a copy of a:

rbinom(xs, args...) = rbinom!(copy(xs), args...)