Julia MethodError for y=1/x - julia

I am absolute Newbie, try to plot y=1/x for x=(1.0,2.0,3.0,4.0,5.0) coming out with MethodError: no method matching /(::Int64, ::NTuple{10,Float64})
I have try y=x^(-1) seem like coming out with same result, documentation didn't help....or I can't find the right one

If you want to apply the operation element wise you need to use broadcasting in Julia, e.g. with "dot-notation":
julia> x=(1.0, 2.0, 3.0, 4.0, 5.0)
(1.0, 2.0, 3.0, 4.0, 5.0)
julia> y = 1 ./ x
(1.0, 0.5, 0.3333333333333333, 0.25, 0.2)
See https://docs.julialang.org/en/v1/manual/arrays/#Broadcasting-1

Related

How do I generate a range of specific numbers given mean?

Given a vector of specified values, for example:
x = c(4.0, 3.7, 3.3, 3.0, 2.7, 2.3, 2.0, 1.7, 1.3, 1.0)
I would like to create a new vector of any length comprised only of values in x sampled randomly, that will result in the combined mean of 3.15. I have tried using the rnorm() function but however, I can only generate random numbers that equate to the mean of 3.15 and not the specified values I wanted. Could anyone point me in the correct direction?
The problem with your question is that there are an infinite number of ways to sample from
x = c(4.0, 3.7, 3.3, 3.0, 2.7, 2.3, 2.0, 1.7, 1.3, 1.0)
to get a mean of roughly 3.15, you just have a specify a probability for each value.
Doing
n = 20
sample(x, n, replace = TRUE)
assumes each value is equally likely and you would get a mean close to 2.5. But if you re-weight the probabilities, you can get closer to what you want. One way of doing this might be
p = 1/(x - 3.15)^2 # or try p = 1/abs(x - 3.15)
sample(x, n, replace = TRUE, prob = p)
where p weights values closer to 3.15 higher so these are more likely to be accepted. It isn't perfect (meaning the true expected value is something like 3.12 and most values are just 2.7, 3.0 and 3.3), but then again there isn't a single solution.
Here's my brute force method:
samp315<-function(n=20, desmean=3.15, distance=0.001) { # create a function with default n=20 and range 3.149-3.151
x<- c(4.0, 3.7, 3.3, 3.0, 2.7, 2.3, 2.0, 1.7, 1.3, 1.0)
samp<-0 # reset samp to 0
i<-0 # reset my counter to zero
while (!between(mean(samp),desmean-distance,desmean+distance) & i<1000000) { # the following will run continuously until a sample (samp) with a mean that falls within the specified range is found, OR until 1 million attempts have been made
samp<-sample(x,n,replace=TRUE) # try to generate a sample of n times from the list of values (x)
i=i+1 # add to counter towards 1 million
}
ifelse(i<1000000,samp,warning("Couldn't find an appropriate sample, please select a lower n, a desired mean closer to 2.5, or a greater distance")) # if the while loop ended because the counter reached a million, exit with an error, otherwise, return the contents of samp.
}
Now, every time you do samp315():
eg<-samp315()
mean(eg)
[1] 3.15
eg
[1] 3.0 3.7 3.0 3.7 3.3 3.7 3.3 3.3 4.0 1.0 1.7 3.0 2.0 4.0 3.7 3.7 2.3 3.3 4.0 3.3
If you want a sample of different length, just place whatever number you wish inside samp315(). The larger the number, however, the longer it will take to find a sample that will get your desired mean.
You can also change your desired mean by setting desmean, and play around with the range by changing distance to whatever the distance (+/-) from your desired mean can be. The default is n=20, with the range from 3.149 to 3.151.
To avoid an infinite loop for highly unlikely combinations of n and range, I set a maximum of 1m samples, after which the function quits with a warning.
As #mickey pointed out, we can weight the probability of each item according to how far it is from the mean. However, that does not quite work, because there are more elements in x lower than than the desired mean, which skews the sampling towards them. We can account for this by adjusting the probabilites relative to how many elements are higher or lower than the desire mean:
x = c(4.0, 3.7, 3.3, 3.0, 2.7, 2.3, 2.0, 1.7, 1.3, 1.0)
n = 100000
xbar=3.15
xhi = x[which(x>xbar)]
xlo = x[which(x<xbar)]
probhi = 1/(xhi-xbar)
problo = 1/(xbar-xlo)
probhi = probhi * length(problo) / length(probhi)
n=1e5
set.seed(1)
y = sample(x, size = n, replace = TRUE, prob = c(probhi,problo))
mean(y)
# [1] 3.150216

matrix of special (besselj) functions

I'm new to julia so I would welcome some advice to improve the following function,
using SpecialFunctions
function rb(x, nu_max)
bj = Array{Complex64}(length(x), nu_max)
nu = 0.5 + (0:nu_max)
# somehow dot broadcast isn't happy
# bj .= [ besselj(_nu,_x)*sqrt(pi/2*_x) for _nu in nu, _x in x]
bj = [ besselj(_nu,_x)*sqrt(pi/2*_x) for _nu in nu, _x in x]
end
rb(1.0:0.1:2.0, 500)
basically, I'm not quite sure what's the recommended way to get a matrix over these two parameters (x and nu). The documentation doesn't offer much information, but I understand that the underlying fortran routine internally loops over nu, so I'd rather not do it again in the interest of performance.
Edit:
I'm asked about the goal; it's to compute the Riccati-Bessel functions $j_1(x,\nu),h_1(x,\nu)$ for multiple values of $x$ and $\nu$.
I've stripped down stylistic questions from the original version to focus on this core issue.
This is a great example where you can take full advantage of broadcasting. It looks like you want the cartesian product between x and nu, where the rows are populated by the values of nu and the columns are x. This is exactly what broadcasting can do — you just need to reshape x such that it's a single row across many columns:
julia> using SpecialFunctions
julia> x = 1.0:0.1:2.0
1.0:0.1:2.0
julia> nu = 0.5 + (0:500)
0.5:1.0:500.5
# this shows how broadcast works — these are the arguments and their location in the matrix
julia> tuple.(nu, reshape(x, 1, :))
501×11 Array{Tuple{Float64,Float64},2}:
(0.5, 1.0) (0.5, 1.1) … (0.5, 1.9) (0.5, 2.0)
(1.5, 1.0) (1.5, 1.1) (1.5, 1.9) (1.5, 2.0)
(2.5, 1.0) (2.5, 1.1) (2.5, 1.9) (2.5, 2.0)
(3.5, 1.0) (3.5, 1.1) (3.5, 1.9) (3.5, 2.0)
⋮ ⋱ ⋮
(497.5, 1.0) (497.5, 1.1) (497.5, 1.9) (497.5, 2.0)
(498.5, 1.0) (498.5, 1.1) (498.5, 1.9) (498.5, 2.0)
(499.5, 1.0) (499.5, 1.1) (499.5, 1.9) (499.5, 2.0)
(500.5, 1.0) (500.5, 1.1) … (500.5, 1.9) (500.5, 2.0)
julia> bj = besselj.(nu,reshape(x, 1, :)).*sqrt.(pi/2*reshape(x, 1, :))
501×11 Array{Float64,2}:
0.841471 0.891207 0.932039 … 0.9463 0.909297
0.301169 0.356592 0.414341 0.821342 0.870796
0.0620351 0.0813173 0.103815 0.350556 0.396896
0.00900658 0.0130319 0.0182194 0.101174 0.121444
⋮ ⋱ ⋮
0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 … 0.0 0.0
Elaborating on my comment above. At first glance, and in general, try to avoid temporary allocations by preallocating arrays and filling them in-place (e.g. using dot broadcasting). Also maybe use #inbounds.
To give you an impression, after
using SpecialFunctions
x = 1.0
nu_max = 3
nu = 0.5 + (0:nu_max)
f(nu,x) = besselj.(nu,x).*sqrt.(pi/2*x)
compare (using BenchmarkTools) performance (and allocations) of
bj = hcat([ besselj.(_nu,x).*sqrt.(pi/2*x) for _nu in nu]...)
and
f.(nu,x)
(Technically the output is not identical, you would have to use vcat above, but anyway)
UPDATE (after OP purified his code):
Ok, I think I (finally) see your real question now (sorry for that). What I said above was about optimizing your original code with respect to how it calls besselj and efficiently processes it's output (see #Matt B.'s post for the nice full broadcast solution here).
IIUC, you want to exploit the fact (I don't know and didn't check if this is actually true) in the calculation of besselj for given nu and x internally there is a summation over nu. In other words you want to use intermediate results of this internal summation to avoid redundant calculations.
As SpecialFunctions's besselj just seems to call the Fortran routine (probably here) I doubt that you can access any of this information. Unfortunately I can't help you along here (I'd probably look for a pure Julia implementation of besselj).

Precision-recall plot

I'd like to make sure that I plotted precision-recall curve. I have following data:
recall = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
precision = [1, 1, 0.8, 0.7, 0.80, 0.65, 0.60, 0.72, 0.60, 0.73, 0.75]
interpolated_precision = [1, 1, 0.80, 0.80, 0.80, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75]
and prepared graph as shown below
precision-recall curve
I'm not sure it is correct since I have seen figures with jiggles. An example is here:
enter image description here
I would be glad if anyone can confirm weather it is wrong or not.
The jagged lines / sawtooth pattern you usually see is more common with more data points (note at least 20 or so in the example figure, vs. exactly 10 for yours), that are coming from actual search results. You said nothing about where your data points are coming from.
The reason the P-R figure often looks jagged is that every increase in recall is usually accompanied by a reduction in precision, at least temporarily, due to the likely addition of false positives. This is also the case in your figure, however, your "dips" seem smaller and your precision remains high throughout.
However, there are two clear errors in your figure in the downward shifts for both precision and interpolated precision, since you are graphing the downward shifts as diagonal lines.
For precision, any downward shift should always be a vertical line. You will not get this from a simple x-y plot of the points you described, e.g. in excel. These vertical lines contribute to the "jagged" look.
For interpolated precision, the graph will always contain perpendicular straight lines, either horizontally or vertically. The definition of interpolated precision essentially requires that (see e.g. https://nlp.stanford.edu/IR-book/html/htmledition/evaluation-of-ranked-retrieval-results-1.html for the correct definition of interpolated precision at any point of recall).
The key here is to realize that the data you are describing should not be graphed as independent observations, but rather as defining the P-R values for the rest of the graph in a particular way.

Where is the syntax error in this Julia function

I have the following code:
using Winston
function testConjecGeneral(n,numTrials)
rangeVec = 2.0
uppBound = zeros(length(rangeVec), 1)
count = 1
for alpha = rangeVec
uppBound(count) = n*renyi([0.25, 0.5, 0.25], alpha)
println("Upper bound: $(uppBound(count))")
count = count+1
end
end
When I try to load the code, using include("testConjecGeneral.jl") at the command prompt, I get ERROR: syntax: missing comma or ) in argument list
while loading /home/ganesh/UROP/YuryJulia/testConjecGeneral.jl, in expression starting on line 3
Can someone help me figure this out?
uppBound(count) = n*renyi([0.25, 0.5, 0.25], alpha)
doesn't look right to me. zeros returns an array and the right way to reference an array item is with square brackets. As written now it looks like it's trying call a function. Does changing that line to:
uppBound[count] = n*renyi([0.25, 0.5, 0.25], alpha)
fix the problem?
I don't think this is a syntax error, but rangeVec is not what you seem to think it is. You assign to rangeVec the Float64 value 2.0 and then you treat rangeVec like an Array, calling length(rangeVec) and looping over alpha = rangeVec. Do you mean for rangeVec to be an Array or a Float64?

R. Taking values from interpolation

I would like to take many values from interpolation at once.
For example, from my data file('int.txt'), I have each "conc1" corresponding to each "depth1" (e.g., 1.1 m, 2.1 m, 3.1 m, 4.1 m, 5.1 m, 6.1 m).
Here, after interpolating my concentration data, I want to take "conc"s at "depth" of 1.2, 2.2, 3.2, 4.2, 5.2 m
Following comments below (I'm editting my question), I made a code like this,
f = approxfun(depth1, conc1, rule=1,method='linear', xout=seq(1.2,5.2,1.0))
i<-approx(depth1, conc1, rule=1,method='linear', xout=seq(1.2,5.2,1.0))
It works well. Here, I have two more questions.
1. Then, how can I make two columns with data from i? Can I add these two columns to my data, 'int'? In this case, I will have no value at the last rows of the new columns.
2. I have one more x, y vector (y= conc2, x=depth2). I have each "conc2" at each "depth2", and "depth2" does not have regular intervals, so which is like 1.3, 2.7, 3.2... Here, after interpolating above, I want to extract all "conc1" values corresponding "depth2".
Please let me know how to do these things. Thank you very much for your help :)
approxfun() generates a function that interpolates between given x and y vectors. You can call that function on a vector to take many approximations at once. There are several customizations you can make, (such as the simple method of interpolation and what to do outside of the data range,) but this should get you started until you specify the need for something more complicated.
?approxfun
f = approxfun(x=c(1.1, 2.1, 3.1, 4.1, 5.1),y=c(1, 3, 5, 2, 4),rule=1,method='constant')
plot(y=f(seq(1.1,5.1,.1)),x=seq(1.1,5.1,.1))
f = approxfun(x=c(1.1, 2.1, 3.1, 4.1, 5.1),y=c(1, 3, 5, 2, 4),rule=1,method='linear')
plot(y=f(seq(1.1,5.1,.1)),x=seq(1.1,5.1,.1))

Resources