xKDR / TSFrames.jl

Timeseries in Julia
MIT License
89 stars 22 forks source link

Functions to count number of periods #180

Open chiraganand opened 3 months ago

chiraganand commented 3 months ago

In xts, they are: nweeks, nseconds, nmonths, etc.

Counting weeks in non-trivial, has to be done like this:

function count(dates::AbstractRange{Date}, ::Type{Week})
    numweeks::Int = 0
    firstmonday = findfirst(x -> dayofweek(x) == 1, dates)
    lastsunday = findlast(x -> dayofweek(x) == 7, dates)
    numweeks += firstmonday == 1 ? 0 : 1
    numweeks += lastsunday == lastindex(dates) ? 0 : 1
    numweeks += div((dates[lastsunday] - dates[firstmonday] + Day(1)).value, 7)
    numweeks
end

Performance

For sorted data

julia> dates = range(Date(1900, 1, 1), Date(2024, 12, 1), step=Day(1))
Date("1900-01-01"):Day(1):Date("2024-12-01")

julia> @btime count(dates, Week)
  182.734 ns (1 allocation: 16 bytes)
6518

julia> dd = collect(dates); @btime count(dd, Week, true)
  191.824 ns (1 allocation: 16 bytes)
6518

For unsorted data:

julia> dates_unsorted = sample(dates, length(dates), replace=true);

julia> @btime count(dates_unsorted, Week, false)
  46.837 μs (1 allocation: 16 bytes)
6518

The above algorithm is $O(1)$ for sorted data but for for unsorted data it is $O(n)$ but that’s the best we can get to. See this Discourse post for some more discussion.

Similarly, other methods can also be written for counting months, etc.