Hi, I have some confusion in applying a function over a column. Here's my function. I just need to shift non-March month-ends to March month-ends. Initially I tried seq.dates, but one cannot give a negative increment (decrement) here. return(as.Date(seq.dates(format(xdate,"%m/%d/%Y"),by="months",len=4)[4]) ) Hence this simple function:> mydate <- as.Date("2006-01-01") > > # Function to shift non-March company-reporting dates to March. > Set2March <- function(xdate){+ # Combines non-March months into March months: + # Dec2006 -> Mar2007 + # Mar2006 -> Mar2006 + # Jun2006 -> Mar2006 + # Sep2006 -> Mar2006 + # VERY Specific code. + Month <- format(xdate,"%m") + wDate <- month.day.year(julian(xdate)) + if (Month=="12"){ + wDate$year <- wDate$year + 1 + wDate$month <- 3 + }else + if (Month=="06"){ + wDate$month <- 3 + }else + if (Month=="09"){ + wDate$month <- 3 + wDate$day <- wDate$day + 1 + }else warning ("No Changes made to the month, since month is not one of (6,9,12)") + cDate <- chron(paste(wDate$month,wDate$day,wDate$year,sep="/")) + return(as.Date(as.yearmon(as.Date(cDate,"%m/%d/%y")),frac=1)) + }> Set2March(as.Date("2006-06-30"))[1] "2006-03-31"> Set2March(mydate)[1] "2006-01-31" Warning message: No Changes made to the month, since month is not one of (6,9,12) in: Set2March(mydate)>Works well when I use it on a single date. Then I try it on a vector:> dc <- seq(as.Date("2006-01-01"),len=10, by="month") > dc[1] "2006-01-01" "2006-02-01" "2006-03-01" "2006-04-01" "2006-05-01" "2006-06-01" "2006-07-01" "2006-08-01" [9] "2006-09-01" "2006-10-01"> sapply(as.vector(dc),Set2March)Error in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3, : unimplemented type 'character' in 'asLogical'>What am I missing here? Shouldn't the function work with the sapply working on each entry? TIA and best, -Tir
Patnaik, Tirthankar wrote:> Hi, > I have some confusion in applying a function over a column. > > Here's my function. I just need to shift non-March month-ends to March > month-ends. Initially I tried seq.dates, but one cannot give a negative > increment (decrement) here. > > return(as.Date(seq.dates(format(xdate,"%m/%d/%Y"),by="months",len=4)[4]) > ) > > Hence this simple function: > >> mydate <- as.Date("2006-01-01") >> >> # Function to shift non-March company-reporting dates to March. >> Set2March <- function(xdate){ > + # Combines non-March months into March months: > + # Dec2006 -> Mar2007 > + # Mar2006 -> Mar2006 > + # Jun2006 -> Mar2006 > + # Sep2006 -> Mar2006 > + # VERY Specific code. > + Month <- format(xdate,"%m") > + wDate <- month.day.year(julian(xdate)) > + if (Month=="12"){ > + wDate$year <- wDate$year + 1 > + wDate$month <- 3 > + }else > + if (Month=="06"){ > + wDate$month <- 3 > + }else > + if (Month=="09"){ > + wDate$month <- 3 > + wDate$day <- wDate$day + 1 > + }else warning ("No Changes made to the month, since month is not > one of (6,9,12)") > + cDate <- chron(paste(wDate$month,wDate$day,wDate$year,sep="/")) > + return(as.Date(as.yearmon(as.Date(cDate,"%m/%d/%y")),frac=1)) > + } >> Set2March(as.Date("2006-06-30")) > [1] "2006-03-31" >> Set2March(mydate) > [1] "2006-01-31" > Warning message: > No Changes made to the month, since month is not one of (6,9,12) in: > Set2March(mydate) > > Works well when I use it on a single date. Then I try it on a vector: > > >> dc <- seq(as.Date("2006-01-01"),len=10, by="month") >> dc > [1] "2006-01-01" "2006-02-01" "2006-03-01" "2006-04-01" "2006-05-01" > "2006-06-01" "2006-07-01" "2006-08-01" > [9] "2006-09-01" "2006-10-01" > > >> sapply(as.vector(dc),Set2March) > Error in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3, > : > unimplemented type 'character' in 'asLogical' > > What am I missing here? Shouldn't the function work with the sapply > working on each entry?1. Your code is not reproducible. Which packages are required? chron? But then, I still do not have as.yearmon()! 2. Why do you use as.vector() in the sapply call? I doubt it can work that way, because as.vector strips the attributes! Uwe Ligges> > TIA and best, > -Tir > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.
On 6/13/07, Patnaik, Tirthankar <tirthankar.patnaik at citi.com> wrote:> Hi, > I have some confusion in applying a function over a column. > > Here's my function. I just need to shift non-March month-ends to March > month-ends. Initially I tried seq.dates, but one cannot give a negative > increment (decrement) here. > > return(as.Date(seq.dates(format(xdate,"%m/%d/%Y"),by="months",len=4)[4]) > ) > > Hence this simple function: > > > mydate <- as.Date("2006-01-01") > > > > # Function to shift non-March company-reporting dates to March. > > Set2March <- function(xdate){ > + # Combines non-March months into March months: > + # Dec2006 -> Mar2007 > + # Mar2006 -> Mar2006 > + # Jun2006 -> Mar2006 > + # Sep2006 -> Mar2006 > + # VERY Specific code. > + Month <- format(xdate,"%m") > + wDate <- month.day.year(julian(xdate)) > + if (Month=="12"){ > + wDate$year <- wDate$year + 1 > + wDate$month <- 3 > + }else > + if (Month=="06"){ > + wDate$month <- 3 > + }else > + if (Month=="09"){ > + wDate$month <- 3 > + wDate$day <- wDate$day + 1 > + }else warning ("No Changes made to the month, since month is not > one of (6,9,12)") > + cDate <- chron(paste(wDate$month,wDate$day,wDate$year,sep="/")) > + return(as.Date(as.yearmon(as.Date(cDate,"%m/%d/%y")),frac=1)) > + } > > Set2March(as.Date("2006-06-30")) > [1] "2006-03-31" > > Set2March(mydate) > [1] "2006-01-31" > Warning message: > No Changes made to the month, since month is not one of (6,9,12) in: > Set2March(mydate) > > > > Works well when I use it on a single date. Then I try it on a vector: > > > > dc <- seq(as.Date("2006-01-01"),len=10, by="month") > > dc > [1] "2006-01-01" "2006-02-01" "2006-03-01" "2006-04-01" "2006-05-01" > "2006-06-01" "2006-07-01" "2006-08-01" > [9] "2006-09-01" "2006-10-01" > > > > sapply(as.vector(dc),Set2March) > Error in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3, > : > unimplemented type 'character' in 'asLogical' > > > > What am I missing here? Shouldn't the function work with the sapply > working on each entry?You can considerable simplify your code with some helper functions: month <- function(x) as.POSIXlt(x)$mon + 1 "month<-" <- function(x, value) { ISOdatetime(year(x) + (value - 1) %/% 12, (value - 1) %% 12 + 1 , mday(x), hour(x), minute(x), second(x), tz(x)) } year <- function(x) as.POSIXlt(x)$year + 1900 "year<-" <- function(x, value) { ISOdatetime(value, month(x), mday(x), hour(x), minute(x), second(x), tz(x)) } marchise <- function(x) { if (month(x) == 12) year(x) <- year(x) if (month(x) %in% c(6, 9, 12)) month(x) <- 3 x } dc <- seq(as.Date("2006-01-01"),len=10, by="month") marchise(dc[[1]]) However, that doesn't work with sapply because the date class seems to get stripped off - I'm not completely why, but perhaps because the date class is a property of the entire vector not the individual values: sapply(marchise, dc) Hadley
Hi, Many thanks for this Hadley, and Uwe, the packages I used were chron, and zoo. Later I'm also using Hadley's reshape. I was able to run the code for a vector thus:> dc <- seq(as.Date("2006-01-01"),len=10,by="month") > dc[1] "2006-01-01" "2006-02-01" "2006-03-01" "2006-04-01" "2006-05-01" "2006-06-01" "2006-07-01" "2006-08-01" [9] "2006-09-01" "2006-10-01"> as.Date(sapply(dc,function(x)Set2March(as.Date(x))))[1] "2006-01-31" "2006-02-28" "2006-03-31" "2006-04-30" "2006-05-31" "2006-03-31" "2006-07-31" "2006-08-31" [9] "2006-03-31" "2006-10-31" Warning messages: 1: No Changes made to the month, since month is not one of (6,9,12) in: Set2March(as.Date(x)) 2: No Changes made to the month, since month is not one of (6,9,12) in: Set2March(as.Date(x)) 3: No Changes made to the month, since month is not one of (6,9,12) in: Set2March(as.Date(x)) 4: No Changes made to the month, since month is not one of (6,9,12) in: Set2March(as.Date(x)) 5: No Changes made to the month, since month is not one of (6,9,12) in: Set2March(as.Date(x)) 6: No Changes made to the month, since month is not one of (6,9,12) in: Set2March(as.Date(x)) 7: No Changes made to the month, since month is not one of (6,9,12) in: Set2March(as.Date(x)) 8: No Changes made to the month, since month is not one of (6,9,12) in: Set2March(as.Date(x))>Basically I ran as.Date on the vector elements (Why?, since the elements are dates anyway?), and then afterwards use as.Date again on the returned vector. Got the answer, but it would be great if I could understand exactly how. TIA and Best, -Tir> -----Original Message----- > From: hadley wickham [mailto:h.wickham at gmail.com] > Sent: Wednesday, June 13, 2007 2:35 PM > To: Patnaik, Tirthankar [GWM-CIR] > Cc: r-help at stat.math.ethz.ch > Subject: Re: [R] Confusion with sapply > > On 6/13/07, Patnaik, Tirthankar <tirthankar.patnaik at citi.com> wrote: > > Hi, > > I have some confusion in applying a function over a column. > > > > Here's my function. I just need to shift non-March > month-ends to March > > month-ends. Initially I tried seq.dates, but one cannot give a > > negative increment (decrement) here. > > > > > return(as.Date(seq.dates(format(xdate,"%m/%d/%Y"),by="months",len=4)[4 > > ]) > > ) > > > > Hence this simple function: > > > > > mydate <- as.Date("2006-01-01") > > > > > > # Function to shift non-March company-reporting dates to March. > > > Set2March <- function(xdate){ > > + # Combines non-March months into March months: > > + # Dec2006 -> Mar2007 > > + # Mar2006 -> Mar2006 > > + # Jun2006 -> Mar2006 > > + # Sep2006 -> Mar2006 > > + # VERY Specific code. > > + Month <- format(xdate,"%m") > > + wDate <- month.day.year(julian(xdate)) > > + if (Month=="12"){ > > + wDate$year <- wDate$year + 1 > > + wDate$month <- 3 > > + }else > > + if (Month=="06"){ > > + wDate$month <- 3 > > + }else > > + if (Month=="09"){ > > + wDate$month <- 3 > > + wDate$day <- wDate$day + 1 > > + }else warning ("No Changes made to the month, since > month is not > > one of (6,9,12)") > > + cDate <- > chron(paste(wDate$month,wDate$day,wDate$year,sep="/")) > > + return(as.Date(as.yearmon(as.Date(cDate,"%m/%d/%y")),frac=1)) > > + } > > > Set2March(as.Date("2006-06-30")) > > [1] "2006-03-31" > > > Set2March(mydate) > > [1] "2006-01-31" > > Warning message: > > No Changes made to the month, since month is not one of (6,9,12) in: > > Set2March(mydate) > > > > > > > Works well when I use it on a single date. Then I try it on > a vector: > > > > > > > dc <- seq(as.Date("2006-01-01"),len=10, by="month") dc > > [1] "2006-01-01" "2006-02-01" "2006-03-01" "2006-04-01" > "2006-05-01" > > "2006-06-01" "2006-07-01" "2006-08-01" > > [9] "2006-09-01" "2006-10-01" > > > > > > > sapply(as.vector(dc),Set2March) > > Error in prettyNum(.Internal(format(x, trim, digits, > nsmall, width, 3, > > : > > unimplemented type 'character' in 'asLogical' > > > > > > > What am I missing here? Shouldn't the function work with the sapply > > working on each entry? > > You can considerable simplify your code with some helper functions: > > month <- function(x) as.POSIXlt(x)$mon + 1 "month<-" <- > function(x, value) { > ISOdatetime(year(x) + (value - 1) %/% 12, (value - 1) > %% 12 + 1 , mday(x), hour(x), minute(x), second(x), tz(x)) } > year <- function(x) as.POSIXlt(x)$year + 1900 "year<-" <- > function(x, value) { > ISOdatetime(value, month(x), mday(x), hour(x), > minute(x), second(x), tz(x)) } > > marchise <- function(x) { > if (month(x) == 12) year(x) <- year(x) > if (month(x) %in% c(6, 9, 12)) month(x) <- 3 > x > } > > dc <- seq(as.Date("2006-01-01"),len=10, by="month") > marchise(dc[[1]]) > > > However, that doesn't work with sapply because the date class > seems to get stripped off - I'm not completely why, but > perhaps because the date class is a property of the entire > vector not the individual > values: > > sapply(marchise, dc) > > Hadley >
Try this. It takes a Date class date and in the first line month.day.year converts unclass(x) to chron. In the last line of the function we convert back to Date class. Its already vectorized so sapply is unneeded: library(chron) f <- function(x) with(month.day.year(unclass(x)), { month <- ifelse(month == 6 | month == 9, 3, month) year <- ifelse(month == 12, year + 1, year) as.Date(paste(year, month, day, sep = "-")) }) Running the last line gives:> # test > f(seq(Sys.Date(), length = 12, by = "month"))[1] "2007-03-13" "2007-07-13" "2007-08-13" "2007-03-13" "2007-10-13" [6] "2007-11-13" "2008-12-13" "2008-01-13" "2008-02-13" "2008-03-13" [11] "2008-04-13" "2008-05-13" On 6/13/07, Patnaik, Tirthankar <tirthankar.patnaik at citi.com> wrote:> Hi, > I have some confusion in applying a function over a column. > > Here's my function. I just need to shift non-March month-ends to March > month-ends. Initially I tried seq.dates, but one cannot give a negative > increment (decrement) here. > > return(as.Date(seq.dates(format(xdate,"%m/%d/%Y"),by="months",len=4)[4]) > ) > > Hence this simple function: > > > mydate <- as.Date("2006-01-01") > > > > # Function to shift non-March company-reporting dates to March. > > Set2March <- function(xdate){ > + # Combines non-March months into March months: > + # Dec2006 -> Mar2007 > + # Mar2006 -> Mar2006 > + # Jun2006 -> Mar2006 > + # Sep2006 -> Mar2006 > + # VERY Specific code. > + Month <- format(xdate,"%m") > + wDate <- month.day.year(julian(xdate)) > + if (Month=="12"){ > + wDate$year <- wDate$year + 1 > + wDate$month <- 3 > + }else > + if (Month=="06"){ > + wDate$month <- 3 > + }else > + if (Month=="09"){ > + wDate$month <- 3 > + wDate$day <- wDate$day + 1 > + }else warning ("No Changes made to the month, since month is not > one of (6,9,12)") > + cDate <- chron(paste(wDate$month,wDate$day,wDate$year,sep="/")) > + return(as.Date(as.yearmon(as.Date(cDate,"%m/%d/%y")),frac=1)) > + } > > Set2March(as.Date("2006-06-30")) > [1] "2006-03-31" > > Set2March(mydate) > [1] "2006-01-31" > Warning message: > No Changes made to the month, since month is not one of (6,9,12) in: > Set2March(mydate) > > > > Works well when I use it on a single date. Then I try it on a vector: > > > > dc <- seq(as.Date("2006-01-01"),len=10, by="month") > > dc > [1] "2006-01-01" "2006-02-01" "2006-03-01" "2006-04-01" "2006-05-01" > "2006-06-01" "2006-07-01" "2006-08-01" > [9] "2006-09-01" "2006-10-01" > > > > sapply(as.vector(dc),Set2March) > Error in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3, > : > unimplemented type 'character' in 'asLogical' > > > > What am I missing here? Shouldn't the function work with the sapply > working on each entry? > > > TIA and best, > -Tir > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >
Thanks Gabor, this is cool! Best, -Tir> -----Original Message----- > From: Gabor Grothendieck [mailto:ggrothendieck at gmail.com] > Sent: Wednesday, June 13, 2007 6:53 PM > To: Patnaik, Tirthankar [GWM-CIR] > Cc: r-help at stat.math.ethz.ch > Subject: Re: [R] Confusion with sapply > > Try this. It takes a Date class date and in the first line > month.day.year converts unclass(x) to chron. In the last > line of the function we convert back to Date class. Its > already vectorized so sapply is unneeded: > > library(chron) > f <- function(x) with(month.day.year(unclass(x)), { > month <- ifelse(month == 6 | month == 9, 3, month) > year <- ifelse(month == 12, year + 1, year) > as.Date(paste(year, month, day, sep = "-")) > }) > > Running the last line gives: > > > # test > > f(seq(Sys.Date(), length = 12, by = "month")) > [1] "2007-03-13" "2007-07-13" "2007-08-13" "2007-03-13" "2007-10-13" > [6] "2007-11-13" "2008-12-13" "2008-01-13" "2008-02-13" "2008-03-13" > [11] "2008-04-13" "2008-05-13" > > > On 6/13/07, Patnaik, Tirthankar <tirthankar.patnaik at citi.com> wrote: > > Hi, > > I have some confusion in applying a function over a column. > > > > Here's my function. I just need to shift non-March > month-ends to March > > month-ends. Initially I tried seq.dates, but one cannot give a > > negative increment (decrement) here. > > > > > return(as.Date(seq.dates(format(xdate,"%m/%d/%Y"),by="months",len=4)[4 > > ]) > > ) > > > > Hence this simple function: > > > > > mydate <- as.Date("2006-01-01") > > > > > > # Function to shift non-March company-reporting dates to March. > > > Set2March <- function(xdate){ > > + # Combines non-March months into March months: > > + # Dec2006 -> Mar2007 > > + # Mar2006 -> Mar2006 > > + # Jun2006 -> Mar2006 > > + # Sep2006 -> Mar2006 > > + # VERY Specific code. > > + Month <- format(xdate,"%m") > > + wDate <- month.day.year(julian(xdate)) > > + if (Month=="12"){ > > + wDate$year <- wDate$year + 1 > > + wDate$month <- 3 > > + }else > > + if (Month=="06"){ > > + wDate$month <- 3 > > + }else > > + if (Month=="09"){ > > + wDate$month <- 3 > > + wDate$day <- wDate$day + 1 > > + }else warning ("No Changes made to the month, since > month is not > > one of (6,9,12)") > > + cDate <- > chron(paste(wDate$month,wDate$day,wDate$year,sep="/")) > > + return(as.Date(as.yearmon(as.Date(cDate,"%m/%d/%y")),frac=1)) > > + } > > > Set2March(as.Date("2006-06-30")) > > [1] "2006-03-31" > > > Set2March(mydate) > > [1] "2006-01-31" > > Warning message: > > No Changes made to the month, since month is not one of (6,9,12) in: > > Set2March(mydate) > > > > > > > Works well when I use it on a single date. Then I try it on > a vector: > > > > > > > dc <- seq(as.Date("2006-01-01"),len=10, by="month") dc > > [1] "2006-01-01" "2006-02-01" "2006-03-01" "2006-04-01" > "2006-05-01" > > "2006-06-01" "2006-07-01" "2006-08-01" > > [9] "2006-09-01" "2006-10-01" > > > > > > > sapply(as.vector(dc),Set2March) > > Error in prettyNum(.Internal(format(x, trim, digits, > nsmall, width, 3, > > : > > unimplemented type 'character' in 'asLogical' > > > > > > > What am I missing here? Shouldn't the function work with the sapply > > working on each entry? > > > > > > TIA and best, > > -Tir > > > > ______________________________________________ > > R-help at stat.math.ethz.ch mailing list > > https://stat.ethz.ch/mailman/listinfo/r-help > > PLEASE do read the posting guide > > http://www.R-project.org/posting-guide.html > > and provide commented, minimal, self-contained, reproducible code. > > >