bdeonovic
bdeonovic

Reputation: 4220

Julia best way to reshape multi-dim array

I have a multi-dimensional array:

julia> sim1.value[1:5,:,:]
5x3x3 Array{Float64,3}:
[:, :, 1] =
  0.201974   0.881742  0.497407
  0.0751914  0.921308  0.732588
 -0.109084   1.06304   1.15962 
 -0.0149133  0.896267  1.22897 
  0.717094   0.72558   0.456043

[:, :, 2] =
  1.28742  0.760712  1.61112
  2.21436  0.229947  1.87528
 -1.66456  1.46374   1.94794
 -2.4864   1.84093   2.34668
 -2.79278  1.61191   2.22896

[:, :, 3] =
 0.649675  0.899028  0.628103
 0.718837  0.665043  0.153844
 0.914646  0.807048  0.207743
 0.612839  0.790611  0.293676
 0.759457  0.758115  0.280334

I have names for the 2nd dimension in

julia> sim1.names
3-element Array{String,1}:
 "beta[1]"
 "beta[2]"
 "s2" 

Whats best way to reshape this multi-dim array so that I have a data frame like:

 beta[1]  | beta[2]   | s2       | chain
 0.201974 |  0.881742 | 0.497407 |   1
 0.0751914|  0.921308 | 0.732588 |   1
-0.109084 |  1.06304  | 1.15962  |   1
-0.0149133|  0.896267 | 1.22897  |   1
 ...      |  ...      | ...      |   ...
 1.28742  |  0.760712 | 1.61112  |   2
 2.21436  |  0.229947 | 1.87528  |   2
-1.66456  |  1.46374  | 1.94794  |   2
-2.4864   |  1.84093  | 2.34668  |   2
-2.79278  |  1.61191  | 2.22896  |   2
 ...      |  ...      | ...      |   ...

Upvotes: 2

Views: 1346

Answers (2)

JobJob
JobJob

Reputation: 4127

Looking at your data, it seems you wanted to basically stack the three matrices output by sim1.value[1:5,:,:] on top of each other vertically, plus add another column with the index of the matrix. The accepted answer of the brilliant and venerable John Myles White seems to put the entire contents of each of those matrices into it's own column.

The below matches your desired output using vcat for the stacking and hcat and fill to add the extra column. JMW I'm sure will know if there's a better way :)

using DataFrames
A = randn(5, 3, 3)
names = ["beta[1]","beta[2]","s2"]

push!(names, "chain")
newA = vcat([hcat(A[:,:,i],fill(i,size(A,1))) for i in 1:size(A,3)]...)
df = DataFrame(newA, Symbol[names...])

note also you can do this slightly more concisely without the explicit calls to hcat and vcat:

newA = [[[A[:,:,i] fill(i,size(A,1))] for i in 1:size(A,3)]...]

Upvotes: 0

John Myles White
John Myles White

Reputation: 2929

At the moment, I think the best way to do this would be a mixture of loops and calls to reshape:

using DataFrames
A = randn(5, 3, 3)

df = DataFrame()
for j in 1:3
  df[j] = reshape(A[:, :, j], 5 * 3)
end

names!(df, [:beta1, :beta2, :s2])

Upvotes: 3

Related Questions