# Tables.jl / ERROR: MethodError: no method matching length(::var"#7#8"{TabOHLCV})

**URL:** <https://discourse.julialang.org/t/tables-jl-error-methoderror-no-method-matching-length-var-7-8-tabohlcv/108915>\
**Category:** Data\
**Created:** [January 17, 2024, 3:20pm UTC](https://discourse.julialang.org/t/tables-jl-error-methoderror-no-method-matching-length-var-7-8-tabohlcv/108915 "2024-01-17T15:20:36Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![FemtoTrader](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/femtotrader/32/309_2.png) [@FemtoTrader](https://discourse.julialang.org/u/FemtoTrader)\
**Post date:** [January 17, 2024, 3:20pm UTC](https://discourse.julialang.org/t/tables-jl-error-methoderror-no-method-matching-length-var-7-8-tabohlcv/108915/1 "2024-01-17T15:20:36Z")

</div>

Hello,

I’ve some vectors defined like so

```julia

const OPEN_TMPL = [
    10.81,
    10.58,
    10.07,
    10.58,
    10.56,
    10.4,
    10.74,
    10.16,
    10.29,
    9.4,
    9.62,
    9.35,
    8.64,
    8.8,
    8.31,
    7.56,
    7.61,
    7.04,
    8.56,
    9.26,
    8.95,
    9.31,
    9.1,
    8.51,
    8.42,
    8.3,
    7.87,
    7.94,
    8.1,
    8.08,
    7.49,
    7.4,
    8.09,
    8.86,
    8.81,
    9.16,
    9.69,
    9.45,
    9.18,
    9.4,
    9.0,
    9.11,
    9.23,
    9.34,
    8.49,
    9.3,
    10.23,
    10.29,
    10.77,
    10.28,
]
const HIGH_TMPL = [
    11.02,
    10.74,
    10.65,
    11.05,
    10.7,
    10.73,
    11.16,
    10.86,
    10.29,
    10.8,
    9.62,
    9.35,
    9.43,
    8.91,
    8.84,
    7.82,
    7.61,
    8.84,
    9.42,
    9.5,
    9.29,
    9.4,
    9.1,
    8.51,
    8.95,
    8.7,
    8.95,
    8.75,
    8.39,
    8.28,
    7.58,
    8.17,
    8.83,
    9.2,
    9.25,
    10.1,
    9.88,
    9.65,
    9.32,
    9.4,
    9.01,
    9.36,
    9.46,
    9.34,
    9.4,
    10.5,
    10.3,
    10.86,
    10.77,
    10.39,
]
const LOW_TMPL = [
    9.9,
    9.78,
    9.5,
    10.47,
    10.26,
    10.4,
    10.12,
    9.91,
    9.4,
    9.11,
    9.12,
    8.5,
    8.55,
    8.21,
    7.34,
    7.53,
    6.5,
    7.04,
    8.15,
    8.72,
    8.6,
    8.89,
    8.14,
    8.24,
    8.06,
    7.7,
    7.87,
    7.94,
    8.0,
    7.37,
    7.49,
    7.38,
    8.05,
    8.79,
    8.67,
    9.16,
    8.9,
    9.17,
    8.6,
    8.92,
    8.99,
    9.11,
    9.11,
    8.43,
    8.42,
    9.26,
    10.0,
    10.19,
    10.15,
    9.62,
]
const CLOSE_TMPL = [
    10.5,
    9.78,
    10.46,
    10.51,
    10.55,
    10.72,
    10.16,
    10.25,
    9.4,
    9.5,
    9.23,
    8.5,
    8.8,
    8.33,
    7.53,
    7.61,
    6.78,
    8.6,
    9.21,
    8.95,
    9.22,
    9.1,
    8.31,
    8.37,
    8.3,
    7.78,
    8.05,
    8.1,
    8.08,
    7.49,
    7.58,
    8.17,
    8.83,
    8.91,
    9.2,
    9.76,
    9.42,
    9.3,
    9.32,
    9.04,
    9.0,
    9.33,
    9.34,
    8.49,
    9.21,
    10.15,
    10.3,
    10.59,
    10.23,
    10.0,
]

const VOLUME_TMPL = [
    55.03,
    117.86,
    301.04,
    157.94,
    39.96,
    42.87,
    191.95,
    55.09,
    131.58,
    249.69,
    77.75,
    197.33,
    107.93,
    35.86,
    269.05,
    34.18,
    209.1,
    241.95,
    162.86,
    112.99,
    66.53,
    87.5,
    349.14,
    44.38,
    45.79,
    139.4,
    46.49,
    27.45,
    16.44,
    83.54,
    15.08,
    60.72,
    140.22,
    171.6,
    209.26,
    199.2,
    165.77,
    61.71,
    29.73,
    12.93,
    4.14,
    12.45,
    42.23,
    133.29,
    120.02,
    255.3,
    111.55,
    108.27,
    48.29,
    81.66,
]

const CLOSE_EQUAL_VALUES_TMPL = repeat([10.46], length(CLOSE_TMPL))

using Dates
const DATE_TMPL =
    collect(range(Dates.Date(2020, 1, 1), step = Dates.Day(1), length = length(CLOSE_TMPL)))

```

I want to build an Tables.jl compatible struct.

I did

```julia
using Tables

struct TabOHLCV
    Index::Vector{Date}
    Open::Vector{Float64}
    High::Vector{Float64}
    Low::Vector{Float64}
    Close::Vector{Float64}
    Volume::Vector{Float64}
    TabOHLCV() = new(DATE_TMPL, OPEN_TMPL, HIGH_TMPL, LOW_TMPL, CLOSE_TMPL, VOLUME_TMPL)
end
Tables.istable(::Type{<:TabOHLCV}) = true
Base.names(table::TabOHLCV) = [:Index, :Open, :High, :Low, :Close, :Volume]
Tables.schema(table::TabOHLCV) = Tables.Schema(names(table), [Dates.Date, Float64, Float64, Float64, Float64, Float64])
Tables.columnaccess(::Type{<:TabOHLCV}) = true
Tables.columns(table::TabOHLCV) = (getfield(table, colname) for colname in fieldnames(typeof(table)))

const TAB_OHLCV = TabOHLCV()

```

Unfortunately when trying to use such an object with DataFrames

```julia
using DataFrames
DataFrame(TAB_OHLCV)

```

or TSFrame

```julia
using TSFrames
TSFrame(TAB_OHLCV)

```

it raises

```
ERROR: MethodError: no method matching length(::var"#7#8"{TabOHLCV})

```

Any idea what I’m missing here?

Kind regards

---

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [January 17, 2024, 4:12pm UTC](https://discourse.julialang.org/t/tables-jl-error-methoderror-no-method-matching-length-var-7-8-tabohlcv/108915/2 "2024-01-17T16:12:54Z")

</div>

I think that you did not correctly implement `Tables.columnnames` method for the value returned by `Tables.columns` (note that it must conform to `AbstractColumns` API).

---

<div class="post-metadata">

**Author:** ![FemtoTrader](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/femtotrader/32/309_2.png) [@FemtoTrader](https://discourse.julialang.org/u/FemtoTrader)\
**Post date:** [January 17, 2024, 4:37pm UTC](https://discourse.julialang.org/t/tables-jl-error-methoderror-no-method-matching-length-var-7-8-tabohlcv/108915/3 "2024-01-17T16:37:39Z")

</div>

```
Tables.columns(table::TabOHLCV) = Dict(colname => getfield(table, colname) for colname in fieldnames(typeof(table)))

```

fix it but TSFrame(table) or DataFrame(table) doesn’t preserve columns order (Index, Open, High, Low, Close, Volume) I’m getting instead `Row │ High Open Low Index Volume Close` for DataFrame and `Index High Open Low Volume Close` for TSFrame.

Is there a solution to preserve column order (ideally without using OrderedDict from DataStructures) ?

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [January 17, 2024, 5:19pm UTC](https://discourse.julialang.org/t/tables-jl-error-methoderror-no-method-matching-length-var-7-8-tabohlcv/108915/4 "2024-01-17T17:19:10Z")

</div>

Make `Tables.columns` return a `NamedTuple` rather than a `Tuple`.

You might also be interested in not defining a struct full of vectors at all. `DataFrame(vec_of_structs)` will work just fine.

You may also be interested in StructArrays.jl for easy conversion between “Array of Structs” and “Struct of Arrays”

---

<div class="post-metadata">

**Author:** ![FemtoTrader](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/femtotrader/32/309_2.png) [@FemtoTrader](https://discourse.julialang.org/u/FemtoTrader)\
**Post date:** [January 17, 2024, 5:32pm UTC](https://discourse.julialang.org/t/tables-jl-error-methoderror-no-method-matching-length-var-7-8-tabohlcv/108915/5 "2024-01-17T17:32:05Z")

</div>

```
Tables.columns(table::TabOHLCV) = (colname=getfield(table, colname) for colname in fieldnames(typeof(table)))

```

doesn’t help

```julia
julia> DataFrame(table)
ERROR: MethodError: no method matching length(::var"#13#14"{TabOHLCV})

```

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [January 17, 2024, 5:35pm UTC](https://discourse.julialang.org/t/tables-jl-error-methoderror-no-method-matching-length-var-7-8-tabohlcv/108915/6 "2024-01-17T17:35:47Z")

</div>

That syntax isn’t right. There are probably simpler syntaxes for making a named tuple from a struct, but here is one MWE

```julia
julia> struct A
           v1
           v2
       end;

julia> a = A(1, 2)
A(1, 2)

julia> nt(a) = (; (n => getfield(a, n) for n in fieldnames(typeof(a)))...)
nt (generic function with 1 method)

julia> nt(a)
(v1 = 1, v2 = 2)

```

---

<div class="post-metadata">

**Author:** ![FemtoTrader](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/femtotrader/32/309_2.png) [@FemtoTrader](https://discourse.julialang.org/u/FemtoTrader)\
**Post date:** [January 17, 2024, 5:48pm UTC](https://discourse.julialang.org/t/tables-jl-error-methoderror-no-method-matching-length-var-7-8-tabohlcv/108915/7 "2024-01-17T17:48:12Z")

</div>

Thanks @pdeffebach

```
Tables.columns(table::TabOHLCV) = (; (colname => getfield(table, colname) for colname in fieldnames(typeof(table)))...)

```

seems to be working

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [January 17, 2024, 7:08pm UTC](https://discourse.julialang.org/t/tables-jl-error-methoderror-no-method-matching-length-var-7-8-tabohlcv/108915/8 "2024-01-17T19:08:48Z")

</div>

Do you really need to create a new struct, or are you creating it just to convert it to some other table type? If the latter, a named tuple of vectors is already a table, so just do:

```julia
TAB_OHLCV = (; OPEN_TMPL, HIGH_TMPL, etc....)

```
