GEBRU
GEBRU

Reputation: 529

convert Bit Array{2} to Array{Bool,1} in julia

So, as the title explains: Is there a way to convert a BitArray{2} type array to a Array{Bool,1}: type array?

PD: the core of the problem is that I am trying to evaluate an Array{float64,2} with a BitArray{2} and I keep getting the following error: ERROR: BoundsError: attempt to access 20×1 Array{Float64,2} at index [Base.Slice(Base.OneTo(20)), Base.LogicalIndex(Bool[0; 0; … ; 0; 0]), Base.Slice(Base.OneTo(1))]

Thanks in advance!

@Mason EDIT:

So, I have been trying to isolate the outliers present in an array{Float64,2}. I found this two functions online and edited them to allow Array{float64,2} arrays as inputs.

function idealf(x::Array{Float64,2})
    y       = sort(x,dims=1);
    n       = length(x);
    j       = floor(Int64, n/4+5/12) # 25%ile is in [y[j], y[j+1]]
    k       = n-j+1        # 75%ile is in [y[k],y[k-1]]
    g       = n/4+5/12 - j   # weighting for the two data surrounding quartiles.
    (1-g).*y[j]+g.*y[j+1], (1-g).*y[k]+g.*y[k-1]
end

function outbox(x::Array{Float64,2}; mbox::Bool=false, gval::Real=NaN, method::Bool=true)
    n = length(x);
    lower_quartile, upper_quartile = idealf(x)
    IQR = upper_quartile-lower_quartile
    cl = cu = 0.0
    if mbox
        if isnan(gval)
            gval=(17.63*n-23.64)/(7.74*n-3.71)
        end
        cl = median(x) - gval*IQR
        cu = median(x) + gval*IQR
    elseif !mbox
        if isnan(gval)
            gval=1.5
        end
        cl = lower_quartile - gval*IQR
        cu = upper_quartile + gval*IQR
    end
    flag = (x.<cl) .| (x.>cu)
    flag=collect(flag) # tunring my BitArray{2} to a Array{float64,2}
    vec = collect(1:n);
    outid  = vec[flag,:] # TROUBLE HERE
    keepid = vec[.!flag] # TROUBLE HERE
    outval = x[flag]
 
    nout = length(outid)
    if method && !mbox
        METHOD = "Outlier detection method using \nthe ideal-fourths based boxplot rule\n"
    elseif method && mbox
        METHOD = "Outlier detection method using \nthe ideal-fourths based boxplot rule\n(using the modification suggested by Carling (2000))\n"
    else
        METHOD = nothing
    end
    return outid, keepid, outval, nout;
end

a=rand(20,1)*10; a[10]=1000.0;a[2]=2000.0;
outbox(a)

And I am having a problem to evaluate on lines: outid = vec[flag,:] and vec[.!flag]. As of today, I couldn't find a solution to go beyond this line of the function. Do you have any idea on how can I evaluate this vector vec en the array flag?

I am trying to run it with an array:

a=rand(20,1)*10;# 20 random numbers in (0,1]
a[10]=1000.0    # input an outlier on index 10...

Upvotes: 0

Views: 1864

Answers (1)

Mason
Mason

Reputation: 3051

To answer your question, you can use collect to turn a BitArray into an Array, and vec to turn a matrix into a vector:

julia> BA = BitArray(rand(Bool, 3, 3))
3×3 BitArray{2}:
 0  1  0
 1  0  1
 1  0  0

julia> collect(BA)
3×3 Array{Bool,2}:
 0  1  0
 1  0  1
 1  0  0

julia> (vec ∘ collect)(BA)
9-element Array{Bool,1}:
 0
 1
 1
 1
 0
 0
 0
 1
 0

Looking at your "PD" though, I suspect this won't solve your underlying issue, but you haven't provided enough information for me to help with that.


Edit in response to OP's edit:

The problem is that you're trying to logically index a Vector with a BitMatrix of size (20, 1). Julia will not automatically treat single column matrices as vectors, unlike Matlab. There are good reasons for this, but I get that it can be surprising.

Instead of using collect on your BitMatrix, you should instead use dropdims(flag, dims=2) to turn flag into a BitVector which is valid for logical indexing.

Here's your original code but with the suggested fix:

#+BEGIN_SRC julia
function idealf(x::Array{Float64,2})
    y       = sort(x,dims=1);
    n       = length(x);
    j       = floor(Int64, n/4+5/12) # 25%ile is in [y[j], y[j+1]]
    k       = n-j+1        # 75%ile is in [y[k],y[k-1]]
    g       = n/4+5/12 - j   # weighting for the two data surrounding quartiles.
    (1-g).*y[j]+g.*y[j+1], (1-g).*y[k]+g.*y[k-1]
end

function outbox(x::Array{Float64,2}; mbox::Bool=false, gval::Real=NaN, method::Bool=true)
    n = length(x);
    lower_quartile, upper_quartile = idealf(x)
    IQR = upper_quartile-lower_quartile
    cl = cu = 0.0
    if mbox
        if isnan(gval)
            gval=(17.63*n-23.64)/(7.74*n-3.71)
        end
        cl = median(x) - gval*IQR
        cu = median(x) + gval*IQR
    elseif !mbox
        if isnan(gval)
            gval=1.5
        end
        cl = lower_quartile - gval*IQR
        cu = upper_quartile + gval*IQR
    end
    flag = dropdims((x.<cl) .| (x.>cu), dims=2) 
    vec = collect(1:n)
    
    outid  = vec[flag]
    keepid = vec[.!flag]
    outval = x[flag]
 
    nout = length(outid)
    if method && !mbox
        METHOD = "Outlier detection method using \nthe ideal-fourths based boxplot rule\n"
    elseif method && mbox
        METHOD = "Outlier detection method using \nthe ideal-fourths based boxplot rule\n(using the modification suggested by Carling (2000))\n"
    else
        METHOD = nothing
    end
    return outid, keepid, outval, nout;
end

a=rand(20,1)*10; a[10]=1000.0;a[2]=2000.0;
outbox(a)
#+END_SRC

#+RESULTS:
: ([2, 10], [1, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], [2000.0, 1000.0], 2)

Upvotes: 1

Related Questions