由于ifelse((剥离属性,因此当涉及到日期时,我使用多个步骤来替换ifelse((。
例如
df <- data.table(a = (1:4),
b = as.Date(c("2012-05-05","2014-05-02","2016-01-02","2011-01-02")),
c = as.Date(c("2014-02-05","2010-01-02","2015-02-02","2012-03-02")))
year <- 2013
df[, d := as.Date(paste0(format(c, "%Y"), "-", format(b, "%m-%d")))]
df[d <= c, d := as.Date(paste0(year, "-", format(b, "%m-%d")))]
上面的例子很简单。在现实生活中,我有一个更复杂的情况,需要使用 3 个日期列进行比较,总共 5 个不同的场景。这是否意味着我需要使用 5 个步骤来完成所有"如果否则"场景?如果是这种情况,我想,data.table的优势没有得到最好的利用。
有没有办法避免使用多个步骤?
那里的代码并不完全混乱。对不起。目的是,如果 B 列的月份和日期的组合早于 C 列,则从 B 列创建一个日期,其中包含 2013 年、月份和日期;否则,请创建一个日期,其中包含 C 列的年份、B 列中的月份和日期。
多亏了@docendo discimus,我更改了代码。
再举一个例子
year1<-2020
year2<-2025
year3<-2030
df<-data.table(a=(1:4),b=as.Date(c("2012-05-05","2014-01-02","2016-10-02","2011-01-02")),
c=as.Date(c("2014-09-05","2010-07-02","2015-02-02","2012-03-02")),
d=as.Date(c("2008-02-06","2009-08-07","2011-04-04","2010-07-10")))
df[,e:=as.Date(paste0(format(c,"%Y"),"-",format(b,"%m-%d")))];
df[e<=c & e>d,e:=as.Date(paste0(year1,"-",format(b,"%m-%d")))]
df[as.Date(paste0(format(c,"%Y"),"-",format(b,"%m-%d")))<=c & as.Date(paste0(format(d,"%Y"),"-",format(b,"%m-%d")))<=d,e:=as.Date(paste0(year2,"-",format(b,"%m-%d")))]
df[as.Date(paste0(format(c,"%Y"),"-",format(b,"%m-%d")))>c,e:=as.Date(paste0(year3,"-",format(b,"%m-%d")))]
上面示例的目的是使用 3 个日期列进行比较。当我说比较时,我的意思是只使用月份和日期,无论年份如何。
If b<=c and b>d, change the year to 2020,
if b<=c and b<=d, change the year to 2025,
if b>c, change the year to 2030.
我需要使用 4 个步骤来完成此操作。第 3 步和第 4 步变得丑陋,因为我在步骤 2 中更改了 e 列的年份,我不能再使用 e 列与 c 和 d 进行比较。有没有办法简化上面的例子?
memisc
包提供了 cases
函数,它通常用来代替对ifelse
的多次调用:
d <- data.frame(x = 1:8)
d$y <- cases(
d$x == 5 -> "Five",
d$x < 3 -> "Less than three",
d$x > 5 -> "More than five",
rep(TRUE, 8) -> "Otherwise"
)
d
这会产生:
x y
1 1 Less than three
2 2 Less than three
3 3 Otherwise
4 4 Otherwise
5 5 Five
6 6 More than five
7 7 More than five
8 8 More than five
这只是一个炫耀cases
的玩具示例,但您可能会发现该功能在您的情况下很有用。请注意,您可以将条件d$x == 5
等替换为任何一系列逻辑向量,只要每个逻辑向量的长度相同,cases
只会捕获第一个计算结果为 TRUE
的向量。