使用" lubridate"编写R函数包含日期的包(例如" 8月14日和#34;)并返回星座

时间:2017-12-29 17:53:32

标签: r date lubridate

声明:编写一个接受日期作为输入的函数,并返回与该日期对应的黄道带的星座(使用Lubridate包)。

问题:当我输入" 12月22日和#34;之间的任何日期时和" 1月19日"。它返回NULLymd应该返回2017-12-22 UTC--2018-01-19 UTC而不是2017-12-22 UTC--2017-01-19 UTC

有没有更好的方法来生成Date / POSIx数据的时间间隔?

zodiac_sign <- function(input){

  library(lubridate)

  input <- ymd(as.character(as.Date(input,format="%B %d")))

  x <- as.Date(c("March 21","April 19","April 20","May 20","May 21","June 20","June 21","July 22","July 23","August 22","August 23","September 22","September 23","October 22","October 23","November 21","November 22","December 21","December 22","January 19","January 20","February 18","February 19","March 20"),format="%B %d")

  x_dateform_char <- as.character(x)

  lst <- list()

  for(i in seq(1,length(x_dateform_char),2)) { 
    lst[[i]] <- c(ymd(x_dateform_char[i]) %--% ymd(x_dateform_char[i+1]))
    if(i==(length(x_dateform_char)-1)){
      break 
    }
  }

  lst <- lst[!sapply(lst, is.null)]

  names(lst) <-
    c("Aries","Taurus","Gemini","Cancer","Leo","Virgo","Libra","Scorpio","Sagittari
      us","Capricorn","Aquarius","Pisces")

  lst

  for(i in 1:length(lst)){
    if(input %within% lst[[i]]){ 
      sign <- names(lst)[i] 
    } }
  sign 
}

2 个答案:

答案 0 :(得分:2)

黄道带标志通常取决于月份的日期,而年份不起任何作用。因此,我想尝试完全忽略评估逻辑中的年份部分。

我考虑的逻辑基于日期(一个月的command-line-tools),该日期在该月划分黄道十二宫。然后,只需从输入值中明确考虑daymonth部分。

day

上述逻辑中使用的zodiac_sign <- function(input){ library(lubridate) input <- ymd(as.character(as.Date(input,format="%B %d"))) # Define data.frame for zodiac_sign zodiac_sign_df <- data.frame(Month = c("March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "January", "February"), Zodiac_Separation_Dt = c(21, 20, 21, 21, 23, 23, 23, 23, 22, 22, 20, 19), LowerSideZS = c("Pisces", "Aries","Taurus","Gemini","Cancer","Leo","Virgo","Libra","Scorpio","Sagittarius","Capricorn","Aquarius"), UpperSideZS = c("Aries","Taurus","Gemini","Cancer","Leo","Virgo","Libra","Scorpio","Sagittarius","Capricorn","Aquarius", "Pisces"), stringsAsFactors = FALSE ) # Filter data with matching month val_df <- zodiac_sign_df[zodiac_sign_df$Month == months(input), ] zodiac_sign <- ifelse( day(input) >= val_df$Zodiac_Separation_Dt, val_df$UpperSideZS, val_df$LowerSideZS) zodiac_sign } 如下所示:

zodiac_sign_df

答案 1 :(得分:1)

我已经重新编辑了您的代码以生成您需要的结果

zodiac_sign <- function(input){
  nms<- input
  library(lubridate)

  input <-ymd(as.character(as.Date(input,format="%B %d")))

  x <- as.Date(c("January 20","February 18",
                 "February 19","March 20","March 21","April 19","April 20","May 20","May 21","June 20",
                 "June 21","July 22","July 23","August 22","August 23","September 22",
                 "September 23","October 22","October 23","November 21","November 22",
                 "December 21","December 22","January 19"),format="%B %d")
  zodiac_name<-c("Aquarius","Pisces","Aries","Taurus","Gemini","Cancer","Leo","Virgo","Libra",
                 "Scorpio","Sagittarius","Capricorn")

  lst=lapply(split(x,rep(1:12,each=2)),function(y){if(y[2]<y[1])y[2]=y[2]+365;c(y[1]%--%y[2])})
  limit=format(ymd(as.character(as.Date("Jan 20",format="%B %d"))),format="%m-%d")
  lower=format(input,format="%m-%d")<limit
  input[lower]=input[lower]+365


  result=which(mapply(`%within%`,list(input),lst),T)
   if(is.matrix(result))setNames(zodiac_name[result[order(result[,1]),2]],nms)
  else setNames(zodiac_name[result],nms)
}
zodiac_sign(c("Jan 10","Mar 20", "Aug 30", "Sep 25","Dec 22","Dec 25"))
     Jan 10      Mar 20      Aug 30      Sep 25      Dec 22      Dec 25 
"Capricorn"    "Pisces"     "Virgo"     "Libra" "Capricorn" "Capricorn"