Reputation: 529
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
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