rposixlt

R: Create Function to Add Water Year Column


I am attempting to add a column to my dataframe that lists the hydrological water year for each sample. A water year is defined as October 1st of the previous calendar year through September 31st. For example, WY 2014 starts 10/1/2013 and ends 9/31/2014.

I found a similar question that was answered here, and the following code was given as a solution:

wtr_yr <- function(dates, start_month=9) {
  # Convert dates into POSIXlt
  dates.posix = as.POSIXlt(dates)
  # Year offset
  offset = ifelse(dates.posix$mon >= start_month - 1, 1, 0)
  # Water year
  adj.year = dates.posix$year + 1900 + offset
  # Return the water year
  adj.year
}

When I try to apply this to my own code I keep getting the error:

Error in rep(value, length.out = nrows) : attempt to replicate an object of type 'closure'

I will include an example of my dataframe along with my adapted version of the solution given above. Any help is greatly appreciated!

NN_Loads_Calculation <- structure(list(Year = c(2008, 2008, 2008, 2008), Month = c(1, 
1, 1, 1), Date.x = structure(c(13879, 13879, 13879, 13879), class = "Date"), 
    Day.x = c(1L, 1L, 1L, 1L), SAC = c(26912331388.8, 26912331388.8, 
    26912331388.8, 26912331388.8), YOLO = c(183493168.56, 183493168.56, 
    183493168.56, 183493168.56), CSMR = c(146794534.848, 146794534.848, 
    146794534.848, 146794534.848), MOKE = c(433043877.8016, 433043877.8016, 
    433043877.8016, 433043877.8016), MISC = c(210405499.9488, 
    210405499.9488, 210405499.9488, 210405499.9488), SJR = c(3425205813.12, 
    3425205813.12, 3425205813.12, 3425205813.12), CCC = c(107649325.5552, 
    107649325.5552, 107649325.5552, 107649325.5552), SWP = c(3393400330.5696, 
    3393400330.5696, 3393400330.5696, 3393400330.5696), CVP = c(2544438604.032, 
    2544438604.032, 2544438604.032, 2544438604.032), WEST = c(2532205726.128, 
    2532205726.128, 2532205726.128, 2532205726.128), RIO = c(19797689599.8336, 
    19797689599.8336, 19797689599.8336, 19797689599.8336), CD = c(3038646871.3536, 
    3038646871.3536, 3038646871.3536, 3038646871.3536), Day.y = c(31, 
    31, 31, 31), Drainage = c(4799740774.51718, 4799740774.51718, 
    4799740774.51718, 4799740774.51718), Diversions = c(130231217.046031, 
    130231217.046031, 130231217.046031, 130231217.046031), C10A = c(2.36, 
    2.36, 2.36, 2.36), C3A = c(0.46, 0.46, 0.46, 0.46), D12 = c(NA_real_, 
    NA_real_, NA_real_, NA_real_), D19 = c(0.91, 0.91, 0.91, 
    0.91), D22 = c(NA_real_, NA_real_, NA_real_, NA_real_), D26 = c(0.98, 
    0.98, 0.98, 0.98), D28A = c(1, 1, 1, 1), D4 = c(0.72, 0.72, 
    0.72, 0.72), MD10A = c(1.95, 1.95, 1.95, 1.95), P8 = c(2.3, 
    2.3, 2.3, 2.3), Island_Div = c(1.32, 1.32, 1.32, 1.32), Island_Drain = c(1.94033333333333, 
    1.94033333333333, 1.94033333333333, 1.94033333333333), Date.x.x = structure(c(1199145600, 
    1199145600, 1199145600, 1199145600), class = c("POSIXct", 
    "POSIXt"), tzone = "UTC"), Day.x.x = c(1, 1, 1, 1), Stockton_Flow = c(50989496.946, 
    50989496.946, 50989496.946, 50989496.946), Stockton_NN = c(18.6241666666667, 
    18.6241666666667, 18.6241666666667, 18.6241666666667), Date.y = structure(c(1199145600, 
    1199232000, 1199318400, 1199404800), class = c("POSIXct", 
    "POSIXt"), tzone = "UTC"), Day.y.y = c(1, 2, 3, 4), Tracy_Flow = c(35847849.746, 
    33992997.964, 33538748.548, 34485101.498), Tracy_NN = c(4.9, 
    4.9, 4.9, 4.9), Banks_NN = c(1.71, 1.71, 1.71, 1.71), Jones_NN = c(1.71, 
    1.71, 1.71, 1.71), SAC_kgd = c(12379.672438848, 12379.672438848, 
    12379.672438848, 12379.672438848), YOLO_kgd = c(84.4068575376, 
    84.4068575376, 84.4068575376, 84.4068575376), SACYOLO_kgd = c(12464.0792963856, 
    12464.0792963856, 12464.0792963856, 12464.0792963856), CSMR_kgd = c(286.2493429536, 
    286.2493429536, 286.2493429536, 286.2493429536), MOKE_kgd = c(844.43556171312, 
    844.43556171312, 844.43556171312, 844.43556171312), MISC_kgd = c(410.29072490016, 
    410.29072490016, 410.29072490016, 410.29072490016), EAST_kgd = c(1540.97562956688, 
    1540.97562956688, 1540.97562956688, 1540.97562956688), SJR_kgd = c(8083.4857189632, 
    8083.4857189632, 8083.4857189632, 8083.4857189632), STOCKTON_kgd = c(949.636889371797, 
    949.636889371797, 949.636889371797, 949.636889371797), TRACY_kgd = c(175.6544637554, 
    166.5656900236, 164.3398678852, 168.9769973402), Islan_Drain_kgd = c(9313.09701615484, 
    9313.09701615484, 9313.09701615484, 9313.09701615484), Total_Input_kgd = c(32526.9290141977, 
    32517.8402404659, 32515.6144183275, 32520.2515477825), WEST_kgd = c(1823.18812281216, 
    1823.18812281216, 1823.18812281216, 1823.18812281216), RIO_kgd = c(14254.3365118802, 
    14254.3365118802, 14254.3365118802, 14254.3365118802), WESTRIO_kgd = c(16077.5246346923, 
    16077.5246346923, 16077.5246346923, 16077.5246346923), CCC_kgd = c(107.6493255552, 
    107.6493255552, 107.6493255552, 107.6493255552), SWP_kgd = c(5802.71456527402, 
    5802.71456527402, 5802.71456527402, 5802.71456527402), CVP_kgd = c(4350.99001289472, 
    4350.99001289472, 4350.99001289472, 4350.99001289472), Water_Exp_kg = c(10261.3539037239, 
    10261.3539037239, 10261.3539037239, 10261.3539037239), Island_Div_kgd = c(171.90520650076, 
    171.90520650076, 171.90520650076, 171.90520650076), Total_Output_kgd = c(26510.783744917, 
    26510.783744917, 26510.783744917, 26510.783744917), Delta_Uptake_kgd = c(6016.14526928067, 
    6007.05649554887, 6004.83067341047, 6009.46780286547), Percent_Uptake = c(18.4958907945311, 
    18.4731103023059, 18.4675294649386, 18.4791553473554)), row.names = c(NA, 
4L), class = "data.frame")

This is the code I tried to use to add the water year column:

NN_Loads_Calculation$wtr_yr <- function(Date.x, start_month=9) {
  # Convert dates into POSIXlt
  dates.posix = as.POSIXlt(Date.x)
  # Year offset
  offset = ifelse(dates.posix$mon >= start_month - 1, 1, 0)
  # Water year
  adj.year = dates.posix$year + 1900 + offset
  # Return the water year
  adj.year
}

Solution

  • You're writing the function (a closure) to NN_Loads_Calculation$wtr_yr, rather than the vectorised output of the function.

    Because the function has a length of one (ie. there's only one function), R tries to repeat it so that it's a vector of functions that's the same length as a column in your data frame. You can't run rep() on a closure, so that's where the code crashes.

    You need to define your function then use it to calculate the new value:

    ## Define the function
    get_water_year <- function(date_x = NULL, start_month = 9) {
      # Convert dates into POSIXlt
      dates.posix = as.POSIXlt(date_x)
      # Year offset
      offset = ifelse(dates.posix$mon >= start_month - 1, 1, 0)
      # Water year
      adj.year = dates.posix$year + 1900 + offset
      # Return the water year
      adj.year
    }
    
    ### Write the function output to the df, rather than the function.
    NN_Loads_Calculation$wtr_yr <- get_water_year(
    date_x = NN_Loads_Calculations$Date.x,
    start_month = 9)