I am attempting to run a Seasonal Kendall trend test using the R package wql
. In order to run the seaKen
function, the time series needs to be a ts
object. The example I am working with involves a three-year time series with one value per day (i.e., three data points for each day of the year). The Seasonal Kendall analysis runs, but all the slope estimates are returned as NA
and the p-values as NaN
. I believe the issue may be related to how I'm converting the data frame from daily observations into a ts
object. Any guidance on how to create a ts
object using the day of the year?
library(tidyverse)
library(wql)
#>
#> Attaching package: 'wql'
#> The following object is masked from 'package:lubridate':
#>
#> years
set.seed(333)
# Example time series
df <- data.frame(
date = seq(as.Date('2021-01-01'),
as.Date('2023-12-31'),
'1 day'),
value = round(rnorm(1095, 100, 50))
)
# Data wrangling
df <- df |>
mutate(season = yday(date),
year = lubridate::year(date)) |>
select(!date) |>
pivot_wider(
names_from = season,
values_from = value
)
head(df)
#> # A tibble: 3 × 366
#> year `1` `2` `3` `4` `5` `6` `7` `8` `9` `10` `11` `12`
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 2021 96 197 -3 114 24 87 162 132 118 72 44 56
#> 2 2022 23 140 97 151 191 151 107 105 55 140 -17 123
#> 3 2023 153 66 164 33 -9 150 56 68 52 66 48 46
#> # ℹ 353 more variables: `13` <dbl>, `14` <dbl>, `15` <dbl>, `16` <dbl>, …
# Create the ts object
df_matrix <- as.matrix(df[, -1])
ts_data <- ts(df_matrix,
start = 1,
deltat = 1/365)
row.names(ts_data) <- c(2021, 2022, 2023)
str(ts_data)
#> Time-Series [1:3, 1:365] from 1 to 1.01: 96 23 153 197 140 66 -3 97 164 114 ...
#> - attr(*, "dimnames")=List of 2
#> ..$ : chr [1:3] "2021" "2022" "2023"
#> ..$ : chr [1:365] "1" "2" "3" "4" ...
head(ts_data)
#> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#> 2021 96 197 -3 114 24 87 162 132 118 72 44 56 102 71 59 106 118 103 168
#> 2022 23 140 97 151 191 151 107 105 55 140 -17 123 186 90 93 219 159 62 125
#> 2023 153 66 164 33 -9 150 56 68 52 66 48 46 15 81 112 119 129 86 169
# Run seasonal kendall analysis
sk_trend <- seaKen(ts_data)
head(sk_trend)
#> sen.slope sen.slope.rel p.value miss
#> 1 NA NA NaN 0.992
#> 2 NA NA NaN 0.992
#> 3 NA NA NaN 0.992
#> 4 NA NA NaN 0.992
#> 5 NA NA NaN 0.992
#> 6 NA NA NaN 0.992
Created on 2025-06-20 with reprex v2.1.1
Turns out there is no need to make the data frame a matrix prior to converting to a ts
object. Also, the seasonTrend
function is needed to see the associated trend results for each "season".
library(tidyverse)
library(wql)
#>
#> Attaching package: 'wql'
#> The following object is masked from 'package:lubridate':
#>
#> years
# Example time series ----
set.seed(333)
df <- data.frame(
date = seq(as.Date("2021-01-01"), as.Date("2023-12-31"), "1 day"),
value = round(rnorm(1095, 100, 50))
)
head(df)
#> date value
#> 1 2021-01-01 96
#> 2 2021-01-02 197
#> 3 2021-01-03 -3
#> 4 2021-01-04 114
#> 5 2021-01-05 24
#> 6 2021-01-06 87
# Convert time series to ts object ----
ts_data <- ts(
df[, 2],
start = 2021,
frequency = 365
)
ts_data
#> Time Series:
#> Start = c(2021, 1)
#> End = c(2023, 365)
#> Frequency = 365
#> [1] 96 197 -3 114 24 87 162 132 118 72 44 56 102 71 59 106 118 103
# Run seasonal trend test ----
sk_trend <- seasonTrend(ts_data, plot = F, type = "slope")
head(sk_trend)
#> season sen.slope sen.slope.rel p.value miss
#> 1 1 28.5 0.2968750 1.000 0
#> 2 2 -65.5 -0.3324873 0.334 0
#> 3 3 83.5 -27.8333333 0.334 0
#> 4 4 -40.5 -0.3552632 1.000 0
#> 5 5 -16.5 -0.6875000 1.000 0
#> 6 6 31.5 0.3620690 1.000 0
Created on 2025-06-23 with reprex v2.1.1