converting vectors to data structure in Julia - julia

I have 2 vectors of 81 values each. and want to save them in a data structure 9 by 9 so that when I use pretty tables to print it I got the following picture (without converting numbers to string and hard coding "," between them)
global c= zeros(81)
global c2 = zeros(81)
global data = zip(eachrow(c), eachcol(c2))
I want to create a 9 by 9 data structure using the above code but it gives me error
ERROR: LoadError: The type Base.Iterators.Zip{Tuple{Base.Generator{Base.OneTo{Int64}, Base.var"#239#240"{Vector{Float64}}}, Base.Generator{Base.OneTo{Int64}, Base.var"#241#242"{Vector{Float64}}}}} is not supported.
Stacktrace:
pretty_table(data ; header = ([-1,-3/4, -1/2, -1/4, 0, 1/4, 1/2, 3/4, 1]), row_names= names)

You can create tuples for each pair of data and print a matrix of those:
julia> c = rand((-1, -0.1, 0.1, 1), 81); c2 = rand((-1, -0.1, 0.1, 1), 81);
julia> titles = [-1,-3/4, -1/2, -1/4, 0, 1/4, 1/2, 3/4, 1];
julia> data = reshape([tuple(c[i], c2[i]) for i in eachindex(c, c2)], 9, 9)
9×9 Matrix{Tuple{Real, Real}}:
...
julia> pretty_table(data; header = titles, row_names = titles)
┌───────┬─────────────┬───────────┬─────────────┬──────────────┬─────────────┬─────────────┬─────────────┬─────────────┬──────────────┐
│ │ -1.0 │ -0.75 │ -0.5 │ -0.25 │ 0.0 │ 0.25 │ 0.5 │ 0.75 │ 1.0 │
├───────┼─────────────┼───────────┼─────────────┼──────────────┼─────────────┼─────────────┼─────────────┼─────────────┼──────────────┤
│ -1.0 │ (-0.1, -1) │ (1, 1) │ (-0.1, -1) │ (0.1, 1) │ (0.1, 1) │ (-1, 1) │ (0.1, 0.1) │ (-0.1, 0.1) │ (-0.1, 1) │
│ -0.75 │ (0.1, 0.1) │ (1, -0.1) │ (0.1, 1) │ (1, 0.1) │ (0.1, 1) │ (0.1, 0.1) │ (0.1, -1) │ (-0.1, 1) │ (-0.1, 1) │
│ -0.5 │ (-1, -1) │ (-1, 1) │ (1, -1) │ (0.1, -1) │ (-1, 0.1) │ (1, -0.1) │ (-1, 0.1) │ (0.1, -0.1) │ (-1, -0.1) │
│ -0.25 │ (-0.1, 0.1) │ (-0.1, 1) │ (-1, -0.1) │ (-1, -1) │ (1, 1) │ (-1, 0.1) │ (-0.1, -1) │ (1, -0.1) │ (-0.1, -0.1) │
│ 0.0 │ (-1, 1) │ (1, 1) │ (1, 0.1) │ (0.1, -1) │ (0.1, 1) │ (-0.1, 0.1) │ (0.1, 0.1) │ (-0.1, -1) │ (-1, -0.1) │
│ 0.25 │ (0.1, 0.1) │ (-1, 1) │ (1, -0.1) │ (1, 0.1) │ (1, -0.1) │ (0.1, 0.1) │ (-1, 1) │ (1, 1) │ (1, 0.1) │
│ 0.5 │ (-1, 1) │ (-1, 1) │ (1, -0.1) │ (-0.1, -1) │ (-0.1, 0.1) │ (-0.1, 1) │ (-1, 1) │ (0.1, -1) │ (-1, -0.1) │
│ 0.75 │ (-1, 1) │ (1, 0.1) │ (0.1, 1) │ (1, 0.1) │ (1, -0.1) │ (0.1, -0.1) │ (0.1, -0.1) │ (-1, -0.1) │ (0.1, 0.1) │
│ 1.0 │ (0.1, -1) │ (-1, -1) │ (-0.1, 0.1) │ (-0.1, -0.1) │ (-0.1, 0.1) │ (1, 1) │ (-0.1, -1) │ (-0.1, 1) │ (-1, 1) │
└───────┴─────────────┴───────────┴─────────────┴──────────────┴─────────────┴─────────────┴─────────────┴─────────────┴──────────────┘

Related

How to shuffle the rows and columns of a DataFrame with a specific seed?

Suppose I have the following DataFrame, and I want to shuffle the rows and columns of the DataFrame with a specific seed value. I tried the following to obtain shuffled indexes, but it gave me a different result every time:
julia> using Random, DataFrames, StatsBase
julia> Random.seed!(123)
julia> df = DataFrame(
col1 = [1, 2, 3],
col2 = [4, 5, 6]
);
julia> idx_row, idx_col = sample.(
[1:size(df, 1), 1:size(df, 2)],
[length(1:size(df, 1)), length(1:size(df, 2))],
replace=false
)
2-element Vector{Vector{Int64}}:
[1, 2, 3]
[2, 1]
julia> idx_row, idx_col = sample.(
[1:size(df, 1), 1:size(df, 2)],
[length(1:size(df, 1)), length(1:size(df, 2))],
replace=false
)
2-element Vector{Vector{Int64}}:
[2, 1, 3]
[2, 1]
As you can see, it's shuffling the values, but it doesn't consider the seed!. How can I shuffle rows and columns of a DataFrame in a reproducible way, like setting a specific seed?
Fortunately, you imported a helpful package named Random. However, you didn't search for the function named shuffle. All can be achieved by the following:
julia> #which shuffle
Random
julia> idx_row, idx_col = shuffle.(
MersenneTwister(123),
[1:size(df, 1), 1:size(df, 2)]
)
2-element Vector{Vector{Int64}}:
[3, 2, 1]
[2, 1]
julia> df[idx_row, idx_col]
3×2 DataFrame
Row │ b a
│ Int64 Int64
─────┼──────────────
1 │ 6 3
2 │ 5 2
3 │ 4 1
The result is reproducible and won't change after each run, despite being a random process.
Additional point
Note that there is a customized dispatch of the shuffle function suitable for shuffling rows of a given DataFrame:
julia> shuffle(MersenneTwister(123), df)
3×2 DataFrame
Row │ a b
│ Int64 Int64
─────┼──────────────
1 │ 3 6
2 │ 1 4
3 │ 2 5
*Note that this only shuffles the rows.
You can choose whatever rng you want, e.g. rng = MersenneTwister(113), and use it to shuffle the range of DataFrame size.
r,c = shuffle.(rng, range.(1,size(df)))
([3, 1, 2], [2, 1])
df[r,c]
3×2 DataFrame
Row │ col2 col1
│ Int64 Int64
─────┼──────────────
1 │ 5 2
2 │ 6 3
3 │ 4 1

Flattening block matrix (matrix of matrices)

Consider a 2x2 matrix of 2x2 blocks, e.g.,
using LinearAlgebra
using StaticArrays
M = zeros(SMatrix{2, 2, Float64, 4}, 2, 2)
M[1,1] = SA[1 0; 0 2]
M[2,2] = SA[0 3; 4 0]
What is the best way to convert M into a 4x4 matrix of scalars?
# how to convert M into this?
M2 = [1 0 0 0;
0 2 0 0;
0 0 0 3;
0 0 4 0]
In my real problem the matrix sizes will be larger, but the general question remains: How to flatten a block matrix into one larger matrix.
I recommend using BlockArrays.jl:
julia> using BlockArrays
julia> mortar(M)
2×2-blocked 4×4 BlockMatrix{Float64, Matrix{SMatrix{2, 2, Float64, 4}}, Tuple{BlockedUnitRange{Vector{Int64}}, BlockedUnitRange{Vector{Int64}}}}:
1.0 0.0 │ 0.0 0.0
0.0 2.0 │ 0.0 0.0
──────────┼──────────
0.0 0.0 │ 0.0 3.0
0.0 0.0 │ 4.0 0.0
You can of course do Matrix(mortar(M)) to get back to a "normal" matrix. However, if you have this kind of data structure you should like staying with the BlockArray.

DataFrames.transform specifying target variable with anonymous function in Julia

I am trying to use transform with an anonymous function (x -> uppercase.(x)) and store the new column as "A" by specifying a target column name (:A).
If I don't specify a target column variable (first transformation below), the new variable is produced fine (i.e. a Vector with 5 elements). However, once I specify the target column (second transformation below), the function returns a Vector of Pairs under the "a_function" name.
How can I produce the desired DataFrame with a new column "A" containing a Vector with 5 elements ("A" to "E")? Why does the second transformation below return a Vector of Pairs with a name different from that specifyed?
using DataFrames
df_1 = DataFrame(a = ["a", "b", "c", "d", "e"])
df_2 = transform(df_1, :a => x -> uppercase.(x)) # first transformation
df_2
Row │ a a_function
│ String String
─────┼────────────────────
1 │ a A
2 │ b B
3 │ c C
4 │ d D
5 │ e E
df_3 = transform(df_1, :a => x -> uppercase.(x) => :A) # second transformation
df_3
5×2 DataFrame
Row │ a a_function
│ String Pair…
─────┼───────────────────────────────────────
1 │ a ["A", "B", "C", "D", "E"]=>:A
2 │ b ["A", "B", "C", "D", "E"]=>:A
3 │ c ["A", "B", "C", "D", "E"]=>:A
4 │ d ["A", "B", "C", "D", "E"]=>:A
5 │ e ["A", "B", "C", "D", "E"]=>:A
Desired outcome DataFrame:
DataFrame(a = ["a", "b", "c", "d", "e"],
A = ["A", "B", "C", "D", "E"])
The reason is operator precedence, if you write:
julia> :a => x -> uppercase.(x) => :A
:a => var"#7#8"()
you see that you have defined only one pair. The whole part uppercase.(x) => :A became the body of your anonymous function.
Instead write (note I added ( and ) around the anonymous function):
julia> :a => (x -> uppercase.(x)) => :A
:a => (var"#9#10"() => :A)
to get what you wanted:
julia> df_3 = transform(df_1, :a => (x -> uppercase.(x)) => :A)
5×2 DataFrame
Row │ a A
│ String String
─────┼────────────────
1 │ a A
2 │ b B
3 │ c C
4 │ d D
5 │ e E
In this case a more standard way to write it would be:
julia> transform(df_1, :a => ByRow(uppercase) => :A)
5×2 DataFrame
Row │ a A
│ String String
─────┼────────────────
1 │ a A
2 │ b B
3 │ c C
4 │ d D
5 │ e E
or even:
julia> transform(df_1, :a => ByRow(uppercase) => uppercase)
5×2 DataFrame
Row │ a A
│ String String
─────┼────────────────
1 │ a A
2 │ b B
3 │ c C
4 │ d D
5 │ e E
The last form is new in DataFrames.jl 1.3, which allows you to pass a function as a destination column name specifier (in this case the transformation was to uppercase the source column name). Of course in this case it is longer, but it is sometimes useful if you define transformations programmatically.

How can I not change the matrix

In Julia, if t is some matrix
t = [1 2; 3 4]
t1 = t
t1[1,1] = 0
t2 = t
t2 gives out same output as t1.
How can I make t2 to equal t?
They are all equal actually:
julia> t = [1 2; 3 4]
2×2 Matrix{Int64}:
1 2
3 4
julia> t1 = t
2×2 Matrix{Int64}:
1 2
3 4
julia> t1[1,1] = 0
0
julia> t2 = t
2×2 Matrix{Int64}:
0 2
3 4
julia> t == t1 == t2
true
julia> t === t1 === t2
true
julia> pointer(t), pointer(t1), pointer(t2) # identical
(Ptr{Int64} #0x00007fd213d37000, Ptr{Int64} #0x00007fd213d37000, Ptr{Int64} #0x00007fd213d37000)
The variables t, t1, and t2 point to the same data, the same memory location. So when you mutate t1 you mutate all.
If you want them to be different, such that only one is modified, you have to use copy:
julia> t = [1 2; 3 4];
julia> t1 = copy(t);
julia> t1[1,1] = 0;
julia> t2 = copy(t); # or just t if you want to avoid the copy
julia> t == t1 == t2
false
julia> pointer(t), pointer(t1), pointer(t2)
(Ptr{Int64} #0x00007fd21220e900, Ptr{Int64} #0x00007fd2142f9630, Ptr{Int64} #0x00007fd2142f9a90)

Min Max Scheme coord.x0 y0 x1 y1

;; makeRectangle -- constructor for 'rectangle
(define makeRectangle
(lambda (x0 y0 x1 y1)
(makeGraph 'rectangle
(list (makePoint x0 y0)
(makePoint x1 y1)))))
(makeRectangle 3 2 1 7) must return (rectangle (point 1 7) (point 3 2))
and I will get the same return for (makeRectangle 1 2 3 7) or (makeRectangle 1 7 3 2), I have to use:
min x0 x1 min y0 y1
max x0 x1 max y0 y1
But I don't know how to do. Could you please help me with this issue? Thanks in advance.
Do you mean something like:
(define makeRectangle
(lambda (x0 y0 x1 y1)
(makeGraph 'rectangle
(makePoint (min x0 x1) (max y0 y1))
(makePoint (max x0 x1) (min y0 y1)))))
such as
-> (makeRectangle 3 2 1 7)
'(rectangle (point 1 7) (point 3 2))
-> (makeRectangle 1 2 3 7)
'(rectangle (point 1 7) (point 3 2))
-> (makeRectangle 1 7 3 2)
'(rectangle (point 1 7) (point 3 2))
-> (makeRectangle 3 7 1 2)
'(rectangle (point 1 7) (point 3 2))

Resources