how to convert multidimensional array to string in idl - idl-programming-language

I have an array of floats or doubles lets call it foo. When I do
size(foo)
I get these 5 dimensions
2 67 52100 4 3498338
I would like to convert it to a string like
str="strcture={arr:"+foo+"}"
so that I can then do
Execute(str)
How can I convert foo to a string dynamically?

I have something to print the declaration of a variable in my library:
IDL> print, mg_variable_declaration(replicate({a: 0.0, b: 1.0}, 10))
replicate({ A: 0.00000, B: 1.00000 }, 10)
It won't get all the data values, though. Just create a variable of the correct type. It might get you part of the way, though.

Related

Is it possible to write a reference to an object in the dictionary value in Python?

Can I use a value in a dictionary as a reference to an object?
Example:
a = 60
b = 70
dict_a = {'command_1':a,'command_2':b}
print(dict_a)
##{'command_1': 60, 'command_2': 70}
When we change "a" was the next change in the dictionary
b = 50
print(dict_a)
##{'command_1': 60, 'command_2': 50}
Yes, you can, but not this way.
What happens here, is this:
b = 70
# b is now reference to anonymous int object with value of 70
dict_a = {'command_1':a,'command_2':b}
# dict_a['command_2'] now points *to the same int object* as b
b = 50
#b now points to another anonymous int object with value of 50
Bottom line. When doing
b=X
something=b
we are pointing both b and something to X. When we later change b to point to Y, something still points to X. when assigning, look at right side of previous assignment.
One of the things you can do is use some smarter object as dict value, whose internal value can be changed by calling some method in it.
eg. assuming a myint class which extends int:
n=myint(5)
mydict=dict(command_1=n)
n.set_value(8)
This should work as n still references the same object as the one in dict.
I don't have python docs at hand, perhaps you can do this with int object as well, but I doubt it, as int objects are immutable.

Julia: short syntax for creating (1,n) array

In Matlab I can write:
[0:n]
to get an array (1,n). For n=2, I get:
0 1 2
How to do the same in Julia? The purpose is to get the same type of array (1,3).
I know I can write [0 1 2], but I want something general like in Matlab.
In julia, the colon operator (in this context, anyway) returns a UnitRange object. This is an iterable object; that means you can use it with a for loop, or you can collect all its contents, etc. If you collect its contents, what you get here is a Vector.
If what you're after is explicitly a RowVector, then you can collect the contents of the UnitRange, and reshape the resulting vector accordingly (which in this case can be done via a simple transpose operation).
julia> collect(1:3).'
1×3 RowVector{Int64,Array{Int64,1}}:
1 2 3
The .' transpose operator is also defined for UnitRange arguments:
julia> (1:3).'
1×3 RowVector{Int64,UnitRange{Int64}}:
1 2 3
However, note the difference in the resulting type; if you apply .' again, you get a UnitRange object back again.
If you don't particularly like having a "RowVector" object, and want a straightforward array, use that in an Array constructor:
julia> Array((1:3).')
1×3 Array{Int64,2}:
1 2 3
(above as of latest julia 0.7 dev version)

The number of occurences of elements in a vector [JULIA]

I have a vector of 2500 values composed of repeated values and NaN values. I want to remove all the NaN values and compute the number of occurrences of each other value.
y
2500-element Array{Int64,1}:
8
43
NaN
46
NaN
8
8
3
46
NaN
For example:
the number of occurences of 8 is 3
the number of occurences of 46 is 2
the number of occurences of 43 is 1.
To remove the NaN values you can use the filter function. From the Julia docs:
filter(function, collection)
Return a copy of collection, removing elements for which function is false.
x = filter(y->!isnan(y),y)
filter!(y->!isnan(y),y)
Thus, we create as our function the conditional !isnan(y) and use it to filter the array y (note, we could also have written filter(z->!isnan(z),y) using z or any other variable we chose, since the first argument of filter is just defining an inline function). Note, we can either then save this as a new object or use the modify in place version, signaled by the ! in order to simply modify the existing object y
Then, either before or after this, depending on whether we want to include the NaNs in our count, we can use the countmap() function from StatsBase. From the Julia docs:
countmap(x)
Return a dictionary mapping each unique value in x to its number of
occurrences.
using StatsBase
a = countmap(y)
you can then access specific elements of this dictionary, e.g. a[-1] will tell you how many occurrences there are of -1
Or, if you wanted to then convert that dictionary to an Array, you could use:
b = hcat([[key, val] for (key, val) in a]...)'
Note: Thanks to #JeffBezanon for comments on correct method for filtering NaN values.
y=rand(1:10,20)
u=unique(y)
d=Dict([(i,count(x->x==i,y)) for i in u])
println("count for 10 is $(d[10])")
countmap is the best solution I've seen so far, but here's a written out version, which is only slightly slower. It only passes over the array once, so if you have many unique values, it is very efficient:
function countmemb1(y)
d = Dict{Int, Int}()
for val in y
if isnan(val)
continue
end
if val in keys(d)
d[val] += 1
else
d[val] = 1
end
end
return d
end
The solution in the accepted answer can be a bit faster if there are a very small number of unique values, but otherwise scales poorly.
Edit: Because I just couldn't leave well enough alone, here's a version that is more generic and also faster (countmap doesn't accept strings, sets or tuples, for example):
function countmemb(itr)
d = Dict{eltype(itr), Int}()
for val in itr
if isa(val, Number) && isnan(val)
continue
end
d[val] = get(d, val, 0) + 1
end
return d
end

How to reshape Arrays quickly

In the following code I am using the Julia Optim package for finding an optimal matrix with respect to an objective function.
Unfortunately the provided optimize function only supports vectors, so I have to transform the matrix to a vector before passing it to the optimize function, and also transform it back when using it in the objective function.
function opt(A0,X)
I1(A) = sum(maximum(X*A,1))
function transform(A)
# reshape matrix to vector
return reshape(A,prod(size(A)))
end
function transformback(tA)
# reshape vector to matrix
return reshape(tA, size(A0))
end
obj(tA) = -I1(transformback(tA))
result = optimize(obj, transform(A0), method = :nelder_mead)
return transformback(result.minimum)
end
I think Julia is allocating new space for this every time and it feels slow, so what would be a more efficient way to tackle this problem?
So long as arrays contain elements that are considered immutable, which includes all primitives, then elements of an array are contained in 1 big contiguous blob of memory. So you can break dimension rules and simply treat a 2 dimensional array as a 1-dimensional array, which is what you want to do. So you don't need to reshape, but I don't think reshape is your problem
Arrays are column major and contiguous
Consider the following function
function enumerateArray(a)
for i = 1:*(size(a)...)
print(a[i])
end
end
This function multiplies all of the dimensions of a together and then loops from 1 to that number assuming a is one dimensional.
When you define a as the following
julia> a = [ 1 2; 3 4; 5 6]
3x2 Array{Int64,2}:
1 2
3 4
5 6
The result is
julia> enumerateArray(a)
135246
This illustrates a couple of things.
Yes it actually works
Matrices are stored in column-major format
reshape
So, the question is why doesn't reshape use that fact? Well it does. Here's the julia source for reshape in array.c
a = (jl_array_t*)allocobj((sizeof(jl_array_t) + sizeof(void*) + ndimwords*sizeof(size_t) + 15)&-16);
So yes a new array is created, but the only the new dimension information is created, it points back to the original data which is not copied. You can verify this simply like this:
b = reshape(a,6);
julia> size(b)
(6,)
julia> size(a)
(3,2)
julia> b[4]=100
100
julia> a
3x2 Array{Int64,2}:
1 100
3 4
5 6
So setting the 4th element of b sets the (1,2) element of a.
As for overall slowness
I1(A) = sum(maximum(X*A,1))
will create a new array.
You can use a couple of macros to track this down #profile and #time. Time will additionally record the amount of memory allocated and can be put in front of any expression.
For example
julia> A = rand(1000,1000);
julia> X = rand(1000,1000);
julia> #time sum(maximum(X*A,1))
elapsed time: 0.484229671 seconds (8008640 bytes allocated)
266274.8435928134
The statistics recorded by #profile are output using Profile.print()
Also, most methods in Optim actually allow you to supply Arrays, not just Vectors. You could generalize the nelder_mead function to do the same.

Multidimensional Array Comprehension in Julia

I'm mucking about with Julia and can't seem to get multidimensional array comprehensions to work. I'm using a nightly build of 0.20-pre for OSX; this could conceivably be a bug in the build. I suspect, however, it's a bug in the user.
Lets say I want to wind up with something like:
5x2 Array
1 6
2 7
3 8
4 9
5 10
And I don't want to just call reshape. From what I can tell, a multidimensional array should be generated something like: [(x, y) for x in 1:5, y in 6:10]. But this generates a 5x5 Array of tuples:
julia> [(x, y) for x in 1:5, y in 6:10]
5x5 Array{(Int64,Int64),2}:
(1,6) (1,7) (1,8) (1,9) (1,10)
(2,6) (2,7) (2,8) (2,9) (2,10)
(3,6) (3,7) (3,8) (3,9) (3,10)
(4,6) (4,7) (4,8) (4,9) (4,10)
(5,6) (5,7) (5,8) (5,9) (5,10)
Or, maybe I want to generate a set of values and a boolean code for each:
5x2 Array
1 false
2 false
3 false
4 false
5 false
Again, I can only seem to create an array of tuples with {(x, y) for x in 1:5, y=false}. If I remove the parens around x, y I get ERROR: syntax: missing separator in array expression. If I wrap x, y in something, I always get output of that kind -- Array, Array{Any}, or Tuple.
My guess: there's something I just don't get here. Anybody willing to help me understand what?
I don't think a comprehension is appropriate for what you're trying to do. The reason can be found in the Array Comprehension section of the Julia Manual:
A = [ F(x,y,...) for x=rx, y=ry, ... ]
The meaning of this form is that F(x,y,...) is evaluated with the variables x, y, etc. taking on each value in their given list of values. Values can be specified as any iterable object, but will commonly be ranges like 1:n or 2:(n-1), or explicit arrays of values like [1.2, 3.4, 5.7]. The result is an N-d dense array with dimensions that are the concatenation of the dimensions of the variable ranges rx, ry, etc. and each F(x,y,...) evaluation returns a scalar.
A caveat here is that if you set one of the variables to a >1 dimensional Array, it seems to get flattened first; so the statement that the "the result is... an array with dimensions that are the concatenation of the dimensions of the variable ranges rx, ry, etc" is not really accurate, since if rx is 2x2 and ry is 3, then you will not get a 2x2x3 result but rather a 4x3. But the result you're getting should make sense in light of the above: you are returning a tuple, so that's what goes in the Array cell. There is no automatic expansion of the returned tuple into the row of an Array.
If you want to get a 5x2 Array from a comprhension, you'll need to make sure x has a length of 5 and y has a length of 2. Then each cell would contain the result of the function evaluated with each possible pairing of elements from x and y as arguments. The thing is that the values in the cells of your example Arrays don't really require evaluating a function of two arguments. Rather what you're trying to do is just to stick two predetermined columns together into a 2D array. For that, use hcat or a literal:
hcat(1:5, 6:10)
[ 1:5 5:10 ]
hcat(1:5, falses(5))
[ 1:5 falses(5) ]
If you wanted to create a 2D Array where column 2 contained the result of a function evaluated on column 1, you could do this with a comprehension like so:
f(x) = x + 5
[ y ? f(x) : x for x=1:5, y=(false,true) ]
But this is a little confusing and it seems more intuitive to me to just do
x = 1:5
hcat( x, map(f,x) )
I think you are just reading the list comprehension wrong
julia> [x+5y for x in 1:5, y in 0:1]
5x2 Array{Int64,2}:
1 6
2 7
3 8
4 9
5 10
When you use them in multiple dimensions you get two variables and need a function for the cell values based on the coordinates
For your second question I think that you should reconsider your requirements. Julia uses typed arrays for performance and storing different types in different columns is possible. To get an untyped array you can use {} instead of [], but I think the better solution is to have an array of tuples (Int, Bool) or even better just use two arrays (one for the ints and one for the bool).
julia> [(i,false) for i in 1:5]
5-element Array{(Int64,Bool),1}:
(1,false)
(2,false)
(3,false)
(4,false)
(5,false)
I kind of like the answer #fawr gave for the efficiency of the datatypes while retaining mutability, but this quickly gets you what you asked for (working off of Shawn's answer):
hcat(1:5,6:10)
hcat({i for i=1:5},falses(5))
The cell-array comprehension in the second part forces the datatype to be Any instead of IntXX
This also works:
hcat(1:5,{i for i in falses(5)})
I haven't found another way to explicitly convert an array to type Any besides the comprehension.
Your intuition was to write [(x, y) for x in 1:5, y in 6:10], but what you need is to wrap the ranges in zip, like this:
[i for i in zip(1:5, 6:10)]
Which gives you something very close to what you need, namely:
5-element Array{(Int64,Int64),1}:
(1,6)
(2,7)
(3,8)
(4,9)
(5,10)
To get exactly what you're looking for, you'll need:
hcat([[i...] for i in zip(1:5, 6:10)]...)'
This gives you:
5x2 Array{Int64,2}:
1 6
2 7
3 8
4 9
5 10
This is another (albeit convoluted) way:
x1 = 1
x2 = 5
y1 = 6
y2 = 10
x = [x for x in x1:x2, y in y1:y2]
y = [y for x in x1:x2, y in y1:y2]
xy = cat(2,x[:],y[:])
As #ivarne noted
[{x,false} for x in 1:5]
would work and give you something mutable
I found a way to produce numerical multidimensional arrays via vcat and the splat operator:
R = [ [x y] for x in 1:3, y in 4:6 ] # make the list of rows
A = vcat(R...) # make n-dim. array from the row list
Then R will be a 3x3 Array{Array{Int64,2},2} while A is a 9x2 Array{Int64,2}, as you want.
For the second case (a set of values and a Boolean code for each), one can do something like
R = [[x y > 5] for x in 1:3, y in 4:6] # condition is y > 5
A = vcat(R...)
where A will be a 9x2 Array{Int64,2}, where true/false is denote by 1/0.
I have tested those in Julia 0.4.7.

Resources