【问题标题】:if statement with dates in R - generalizing per year带有 R 中日期的 if 语句 - 每年概括
【发布时间】:2019-03-15 15:44:38
【问题描述】:

我从以下问题开始寻求泛化性质:if statement with dates in R

df <- data.frame(date = as.Date(c("16.04.2015", "04.08.2014", "11.09.2013",
                                  "20.11.2015", "04.04.2014"), '%d.%m.%Y'))

我想识别 07-15 (%m-%d) 和 12-31 之间的所有日期,例如

> date        value
> 16.04.2015  0
> 04.08.2014  1
> 11.09.2013  1
> 20.11.2015  1
> 04.04.2014  0

我的解决方案基于@rawr 在上述问题中发布的解决方案:

区间函数:

`%between%` <- function(x, interval) x >= interval[1] & x <= interval[2]

具有所有可能开头的向量:

begi <- as.Date(sprintf('%s-07-15',1993:2018))

# Vector with all the possible intervals
dates <- as.Date(c(sprintf('%s-07-15',1993:2018), sprintf('%s-12-31',1993:2018))) 

使用函数循环

df$value <- NA

for (i in length(begi)) {
  ind<-which(format(df$date,"%Y") == format(begi[i], "%Y"))
  df$value[ind] <- 1*(df$date[ind] %between% as.Date(c(begi[i], 
                dates[i+length(begi)])))
}

如果我一一运行i,我会得到想要的结果。但是,如果我在最后一个i 运行循环,它会覆盖整个列,而不是仅使用ind 指示的位置。为什么?

【问题讨论】:

  • 你的 for 循环只运行了 1 次。正确的说法应该是:for(i in 1:length(begi) )。有关解决此问题的更好方法,请参阅下面的答案。

标签: r date if-statement


【解决方案1】:

您可以将日期格式化为%m-%d 并使用字符串比较

df$value <- as.numeric(format(df$date, '%m-%d') %between% c('07-15', '12-31'))
df
#         date value
# 1 2015-04-16     0
# 2 2014-08-04     1
# 3 2013-09-11     1
# 4 2015-11-20     1
# 5 2014-04-04     0

【讨论】:

    【解决方案2】:
    df$leapyear <- ifelse(as.integer(format(df$date, "%Y")) %% 4 == 0, 1, 0)
    df$leapyear <- ifelse(as.integer(format(df$date, "%Y")) %% 100 == 0, 0, 1)
    df$leapyear <- ifelse(as.integer(format(df$date, "%Y")) %% 400 == 0, 1, 0)
    
    df[format(df$date, "%j") > ifelse(df$leapyear == 0, 197, 196), ]
    

    感谢@RyanD 指出基于年份的子集未能考虑闰年

    【讨论】:

    • format(as.Date('2018-07-15'), "%j") &gt; 196 返回FALSE。如果您将其更改为&gt;=,它将返回TRUE,但随后format(as.Date('2016-07-14'), "%j") &gt;= 196 将返回TRUE。所以这个方法在闰年是行不通的。
    • 甚至没有考虑闰年。有趣的点@RyanD。
    • 它应该返回一个 TRUE/FALSE 语句向量,指示满足此条件的行。 &gt; 在提供的数据集上工作,但显然任何操作数都可以使用,我认为这不是重点。
    • 其实你是完全正确的!我完全忽略了闰年。
    • 这应该可以工作:df[format(df$date, "%j") &gt; ifelse(as.integer(format(df$date, "%Y")) %% 4 == 0, 197, 196), ]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多