Is there a built-in lagged operator function in julia? I.e., a function of the form:
lagop(op,array,offset)
that returns something like
[array[i + offset] (op) array[i] for i in 1:length(array)-offset]
For successive differences, there is the diff function. For sums either of the following works:
x = collect(1:10)
x[1:end-1]+x[2:end]
[x[i]+x[i+1] for i in 1:length(x)-1]
Is there a general function to accomplish tasks like this?
You mention the zoo library in R, which is for time series. If that's your use case, you will find lag implemented in TimeSeries.jl: http://timeseriesjl.readthedocs.io/en/latest/apply.html#lag It may not be exactly what you want, though.
Related
I have some code that runs fine and does what I want, although there may be a simpler more elegant solution, this works :
round(Int16, floor(rand(TruncatedNormal(150,20,50,250))))
However when I try to execute it multiple times, using map, it throws an error saying it doesn't like the Int16 specification, so this:
map(round(Int16, floor(rand(TruncatedNormal(150,20,50,250)))), 1:2)
throws this error
ERROR: MethodError: objects of type Int16 are not callable
I just want to run it twice (in this case) and sum the results. Why is it unhappy? Thx. J
The first argument to map is a function. So, with your code, Julia is trying to make a function call:
round(Int16, floor(rand(TruncatedNormal(150,20,50,250))))()
But the output of round(Int16, ...) isn't a function, it's a number, so you cannot call it. That's why the error says "objects of type Int16 are not callable." You could fix this by using an anonymous function:
map(() -> round(Int16, floor(rand(TruncatedNormal(150,20,50,250)))), 1:2)
But the "Julian" way to do this is to use a comprehension:
[round(Int16, floor(rand(TruncatedNormal(150,20,50,250)))) for _ in 1:2]
EDIT:
If you are going to sum the results, then you can use something that looks like a comprehension but is called a generator expression. This is basically everything above with the [ ] around the expression. A generator expression can be used directly in functions like sum or mean, etc.
sum(round(Int16, floor(rand(TruncatedNormal(150,20,50,250)))) for _ in 1:2)
The advantage to generator expressions is that they don't allocate the memory for the full array. So, if you did this 100 times and used the sum approach above, you wouldn't need to allocate space for 100 numbers.
This goes beyond the original question, but OP wanted to use the sum expression where the 2 in 1:2 is a 1-element vector. Of course, if the input is always a 1-element vector, then I recommend first(x) like the comments. But this is a nice opportunity to show the importance of breaking things down into functions frequently in Julia. For example, you could take the entire sum expression and define a function
generatenumbers(n::Integer) = sum(... for _ in 1:n)
where n is a scalar. Then if you have some odd array expression for n (1-element vector, many such ns in a multi-dim array, etc.), you can just do:
generatenumbers.(ns)
# will apply to each element and return same shape as ns
If the de-sugaring logic is more complex than applying element-wise, you can even define:
generatenumbers(ns::AbstractArray) = # ... something more complex
The point is to define an "atomic" function that expresses the statement or task you want clearly, then use dispatch to apply it to more complicated data-structures that appear in practical code. This is a common design pattern in Julia (not the only option, but an effective one).
Adding on the answer from #darsnack.
If you want to run it multiple times in order to keep the results (it wasn't clear from the question). Then you could also ask rand to produce a vector by doing the following (and also making the type conversion through the floor call).
Moving from:
map(round(Int16, floor(rand(TruncatedNormal(150,20,50,250)))), 1:2)
to:
floor.(Int16, rand(TruncatedNormal(150,20,50,250), 2))
The documentation is here.
Is there a simpler way to do apply a function in Julia to nested array than defining a new function? - e.g. for this simple example:
a = collect(1:10)
b = [ a*i for i in 100:100:400]
arraylog(x) = log.(x) ## Need to define an extra function to do the inner array?
arraylog.(b)
I would use a comprehension just like you used it to define b: [log.(x) for x in b].
The benefit of this approach is that such code should be easy to read later.
EDIT
Referring to the answer by Tasos actually a comprehension implicitly defines an anonymous function that is passed to Base.Generator. In this use case a comprehension and map should be largely equivalent.
I assumed that MR_MPI-BGC wanted to avoid defining an anonymous function.
If it were allowed one could also use a double broadcast like this:
(x->log.(x)).(b)
which is even shorer but I thought that it would not be very readable in comparison to a comprehension.
You could define it as a lambda instead.
Obviously the distinction may be moot, depending on how you're using this later in your code, but if all you want is to not waste a line in your code for the sake of conciseness, you could easily dump this inside a map statement, for instance:
map( x->log.(x), b )
or, if you prefer do syntax:
map(b) do x
log.(x)
end
PS. I'm not familiar with a syntax which allows the broadcasted version of a function to be plugged directly into map, but if one exists it would be even cleaner than a lambda here ... but alas 'map( log., b )' is not valid syntax.
Is it possible to do something like this?
trace( for(a in array) a );
I've seen it used when populating an array:
var numbers = [ for (i in 0...100) i ];
But doesn't seem to work as an overall expression?
for can be used "as a value" in array comprehension (as you mentioned) as well as map comprehension. The same is true for while and do...while.
In other places, loops cannot be used like this. Everything is an expression explains this well, using pretty much the same trace example you gave:
Some expressions, such as loops or var declarations don't make any sense as values, so they will be typed as Void and thus won't be able to be used where value is expected. For example the following won't compile:
trace(for (i in 0...10) i); // ERROR: Cannot use Void as value
I'm looking for an equivalent in Matlab to do the same as Apply in Mathematica. There it works like this
fct=#1+#2^2+#3^3+#4^4&;
Apply[fct,{a,b,c,d}]=f[a,b,c,d]
In Matlab, it's easy with a cell like this
fct=#(x1,x2,x3,x4) x1+x2^2+x3^3+x4^4;
mycell={a,b,c,d};
fct(mycell{:})
because mycell{:}=a,b,c,d is a valid comma-separated list of arguments for fct (see here).
Now, I would like to do the same with an array, e.g. like this:
myarrray=[a,b,c,d];
fct(myarray(:))
but this doesn't work. Sadly, things like fct(num2cell(myarray){:}) don't work either.
The problem here is that I would like to use the function as a one-liner (the array already exists, it can be called by its name). The reason for this is that the function should be an element of a struct.
Of course, in reality, my function looks differently. Note that I'm not looking for arrayfun which maps a function over an array.
(side note: In Mathematica, I can even write Apply[#1+#2^2+#3^3+#4^4&,{a,,b,c,d}] and there is even an infix notation for Apply making it more concise.)
I have a simple problem with structures.
Lets create:
x(1).a(:, :) = magic(2);
x(2).a(:, :) = magic(2)*2;
x(3).a(:, :) = magic(2)*3;
how to list a(1, 1) from all x-es?
i wanted to do it like:
x(1, :).a(1,1)
but there is an error "Scalar index required for this type of multi-level indexing."
How to approach it? I know I can do it with a loop, but that's probably the worst solution :)
Thanks!
This is not the best datastructure to use if this is the sort of query you'd like to make on it, precisely because this sort of indexing cannot be done directly.
However, here is one approach that works:
cellfun(#(X) X(1,1), {x.a})
The syntax {x.a} converts x from a 'struct array' into a cell array. Then we use cellfun to apply a function as a map over the cell array. The anonymous function #(X) X(1,1) takes one argument X and returns X(1,1).
You can also get your data in this way:
B = cat(3,x.a);
out = reshape(B(1,1,:),1,[]);
By the way, loops are not evil. Sometimes they are even faster than vectorized indexation. Try it both ways, see what suits you best in terms of:
Speed - use the profiler to check
Code clarity - depends on the context. Sometimes vectorized code looks better, sometimes the opposite.