How to create samples using sampling technique from existing arrays? - julia

I have two arrays as shown below,
x = collect(range(1, 10, length=10))
y = colelct(range(1, 10, length=10))
I would like to how can i convert them into either Sobol or Uniform sample, using their algorithm.
Thanks, look forward to suggestions!

Are you trying to sample values (uniformly) from 1:10? If so, you can just pass the collection to rand:
julia> rand(1:10, 5)
5-element Vector{Int64}:
10
5
5
8
8
for the x you gave above, that would be
julia> x = collect(range(1, 10, length=10)) ;
julia> rand(x, 5)
5-element Vector{Float64}:
2.0
4.0
6.0
7.0
3.0
I'm not sure about Sobol sampling.

Related

How to round to nearest multiple?

Is there an idiomatic way to round to the nearest multiple of a number?
number multiple result
12.2 0.5 12.0
12.2 0.25 12.25
12.4 0.5 12.5
You can define a function:
round_step(x, step) = round(x / step) * step
Usage:
julia> round_step(12.2, 0.25)
12.25
Such a function is actually used internally in Base for rounding numbers to a certain number of digits in a certain base:
julia> Base._round_step(12.2, 0.25, RoundNearest)
12.25
However since this is an internal implementation detail you shouldn't rely on this function. This function in turn calls _round_invstep.
julia> Base._round_invstep(12.2, 4, RoundNearest)
12.25
julia> Base._round_invstep(12.4, 2, RoundNearest)
12.5
Which performs the operation round(x * invstep, r) / invstep.
Because your examples happen to correspond to 0.1 in base 4 and base 2 you can also use round directly for these particular cases:
julia> round(12.2; base=2, digits=1)
12.0
julia> round(12.2; base=4, digits=1)
12.25
julia> round(12.4; base=2, digits=1)
12.5

What is the alternate of numpy.digitize() function in Julia?

I would like to know, how may I replicate the numpy.digitize() functionality in julia?
I am trying to convert this python example to Julia.
Python Example
x = np.array([0.2, 6.4, 3.0, 1.6])
bins = np.array([0.0, 1.0, 2.5, 4.0, 10.0])
inds = np.digitize(x, bins)
Output: array([1, 4, 3, 2], dtype=int64)
I tried using searchsorted function in Julia but it doesn't replicate the output form python.
Please suggest a solution to this problem.
Thanks in advance!!
You may use searchsortedlast with broadcasting:
julia> x = [0.2, 6.4, 3.0, 1.6]
4-element Array{Float64,1}:
0.2
6.4
3.0
1.6
julia> bins = [0.0, 1.0, 2.5, 4.0, 10.0]
5-element Array{Float64,1}:
0.0
1.0
2.5
4.0
10.0
julia> searchsortedlast.(Ref(bins), x)
4-element Array{Int64,1}:
1
4
3
2

Julia: How can we compute the adjoint or classical adjoint (Linear Algebra)?

I wan to compute the classical adjoint in Julia 1.0
For this I copied the matrix given as an example in wikipedia
julia> B = [-3 2 -5; -1 0 -2; 3 -4 1]
3×3 Array{Int64,2}:
-3 2 -5
-1 0 -2
3 -4 1
That seems to me to compute the transpose of B and not its adjoint. Instead, we should get this (from wikipedia):
and tried to get its adjoint using the adjoint() function which is mentionned in the Julia documentation here despite that the doc does not specifically said what this function does
julia> adjoint(B)
3×3 Adjoint{Int64,Array{Int64,2}}:
-3 -1 3
2 0 -4
-5 -2 1
Instead I want to get this:
In Matlab I get indeed:
>> adjoint(B)
ans =
-8.0000 18.0000 -4.0000
-5.0000 12.0000 -1.0000
4.0000 -6.0000 2.0000
Julia's adjoint is defined as the transpose of the complex conjugate of the input matrix. However, you seem to want the adjugate matrix:
The adjugate has sometimes been called the "adjoint", but today the "adjoint" of a matrix normally refers to its corresponding adjoint operator, which is its conjugate transpose.
You can compute the adjugate matrix by inverting, and then multiplying by the determinant:
julia> det(B) * inv(B)
3×3 Array{Float64,2}:
-8.0 18.0 -4.0
-5.0 12.0 -1.0
4.0 -6.0 2.0
Thanks to #Antoine Levitt and #Syx Pek on the Julia Slack for giving the suggestion of inverting and multiplying by determinant.
Original answer:
The adjugate matrix seems to be the transpose of the matrix of cofactors. Below is a naïve implementation of finding cofactors:
# import Pkg; Pkg.add("InvertedIndices")
using InvertedIndices # for cleaner code, you can remove this if you really want to.
function cofactor(A::AbstractMatrix, T = Float64)
ax = axes(A)
out = similar(A, T, ax)
for col in ax[1]
for row in ax[2]
out[col, row] = (-1)^(col + row) * det(A[Not(col), Not(row)])
end
end
return out
end
Then, to find the adjugate, you only need to transpose (transpose(cofactor(B))).
The answer is:
julia> cofactor(B, Float64) |> transpose
3×3 Transpose{Float64,Array{Float64,2}}:
-8.0 18.0 -4.0
-5.0 12.0 -1.0
4.0 -6.0 2.0
which is equivalent to what Matlab gives.
Edit: #Antoine Levitt on the Julia slack pointed out that this is essentially a rescaled inverse matrix, so if you figure out the scaling factor, you can just do inv(B) * scaling_factor (in the case of this matrix, it's 6).

How to split a continuous variable into intervals of equal length (defined number) and list the interval with cut points only in R?

I would like to divide a set of data into four equal size interval, e.g.:
x=c(0:10)
G1: [0,2.5)
G2: [2.5,5)
G3: [5,7.5)
G4: [7.5,10]
Is there anyway I can split the data into intervals of equal length (say four in this case) and get the below list including the min and max values:
0 2.5 5 7.5 10
Thanks!
You're looking for cut
cut(1:10, c(1, seq(2.5, 10, by=2.5)), include.lowest = T)
# [1] [1,2.5] [1,2.5] (2.5,5] (2.5,5] (2.5,5] (5,7.5] (5,7.5] (7.5,10]
# [9] (7.5,10] (7.5,10]
# Levels: [1,2.5] (2.5,5] (5,7.5] (7.5,10]
If you just want the evenly spaced breaks, use seq
x <- 0:10
seq(min(x), max(x), len=5)
# [1] 0.0 2.5 5.0 7.5 10.0
data.frame(x, breaks=cut(x,breaks = 5, labels=c("1","2.5","5","7.5","10")) )
does the work?
(The trick is in the cut function of course)

Function or loop to subset moving average in R

I'm new to loops and functions in R.
Imagine I have measurements at every 0.1 units from 1.0 to 3.5 for four samples (A, B, C, D).
I want to find the average measurements (+/- 0.2 units) near 1.5, 2.5, and 3.5. So, for 1.5 I'm averaging the values at c(1.3, 1.4, 1.5, 1.6, and 1.7), etc.
How can I write a statement to summarize those three average values for all four samples? I think it might start something like this:
X <- (1.5, 2.5, 3.5)
for (i in X)
{
avg <- colMeans(subset(data,data$measurement > (i - 0.2) & data$measurement < (i + 0.2)))
}
I've also considered using '[' instead too:
colMeans(data[data$measurement > (i-0.2) & data$measurement < (i+0.2)])
Thanks for the help so far, sqldf is a really nice tool, the example does just what I want!
However, I can't get it to work with the real data set. I modified the code so it looks like (sorry, this doesn't correspond with the sample data set anymore):
M <- sqldf("select r.i,avg(w.X1),avg(w.X2),avg(w.X3),avg(w.X4)
from Y r, Y w
where w.i betreen r.i - 1 and r.i + 1
group by r.i
having r.i+0.0 in (600, 700, 800)")
To contextualize it, I am trying to summarize the average of all points from 599–601, 699–701 and 799–801, for four columns named X1, X2, X3, X4. I named this data frame 'Y'. The rows are actually wavelengths, and the data points the amount of light reflected at that wavelength.
Do you see anything wrong with the above code? -- It creates a matrix with the right dimensions, but the averages don't match with what they should from the larger dataset. I'm wondering if I'm not understanding something in the code, for instance, the importance of the 'w' variable.
Proper indexing is faster than the loop.
library(zoo)
set.seed(1)
x <- as.character(seq(1,3.5,.1))
z <- zoo(data.frame(a=rnorm(length(x)),
b=rnorm(length(x)),
c=rnorm(length(x))),
x)
z2 <- rollmean(z, k = 5, align = "center")[as.character(seq(1,3.5,.5)),]
> z2
a b c
1.5 0.46601479 0.40153999 0.2007418
2 0.31015536 -0.22912642 0.4673692
2.5 -0.04141133 0.31978341 0.4350507
3 0.63816023 -0.07509644 -0.3622883
> data.frame(z2, index = index(z2))
a b c index
1.5 0.46601479 0.40153999 0.2007418 1.5
2 0.31015536 -0.22912642 0.4673692 2
2.5 -0.04141133 0.31978341 0.4350507 2.5
3 0.63816023 -0.07509644 -0.3622883 3
If you want the partial fills on the edges where the window is less than 5 wide:
> rollapply(z, width = 5, align = "center", partial = TRUE, FUN = mean)[as.character(seq(1,3.5,.5)),]
a b c
1 -0.42614637 -0.70156598 0.21492677
1.5 0.46601479 0.40153999 0.20074176
2 0.31015536 -0.22912642 0.46736921
2.5 -0.04141133 0.31978341 0.43505071
3 0.63816023 -0.07509644 -0.36228832
3.5 -0.47521823 0.22239574 -0.05024676
If the windows sizes are irregular, but equally spaced as mentioned in the comment:
> z2 <- as.data.frame(z)
> z2$i <- row.names(z2)
> library(sqldf)
> sqldf("select a.i,avg(b.a),avg(b.b),avg(b.c)
from z2 a, z2 b
where b.i between a.i - .21 and a.i + .21
group by a.i
having a.i+0.0 in (1.5,2.0,2.5,3.0,3.5)")
i avg(b.a) avg(b.b) avg(b.c)
1 1.5 0.46601479 0.40153999 0.20074176
2 2 0.31015536 -0.22912642 0.46736921
3 2.5 -0.04141133 0.31978341 0.43505071
4 3 0.63816023 -0.07509644 -0.36228832
5 3.5 -0.47521823 0.22239574 -0.05024676

Resources