【问题标题】:How to combine two subsets of dates into one column?如何将两个日期子集合并为一列?
【发布时间】:2018-11-21 16:04:51
【问题描述】:

我有这些日期问题之一。

dfr 数据框中,由于合并,我有两个日期列,只有正确年份的日期有效,我希望它在一个额外的列中。

> head(dfr, 4)
   id year some.vars     date17     date18
1 101 2017         8 2017-11-21 2018-11-21
2 101 2018         0 2017-11-21 2018-11-21
3 102 2017         2 2017-11-23 2018-11-23
4 102 2018         9 2017-11-23 2018-11-23

所以我像往常一样这样做

dfr$date <- 0
dfr$date[dfr$year == 2017] <- dfr$date17[dfr$year == 2017]
dfr$date[dfr$year == 2018] <- dfr$date18[dfr$year == 2018]

但它给了一个十进制形式的日期列,

> head(dfr, 4)
   id year some.vars     date17     date18       date
1 101 2017         8 2017-11-21 2018-11-21 1511218800
2 101 2018         0 2017-11-21 2018-11-21 1542754800
3 102 2017         2 2017-11-23 2018-11-23 1511391600
4 102 2018         9 2017-11-23 2018-11-23 1542927600

我可能必须通过指定originstrftime等再次使用as.POSIXct() 进行格式化。但我认为这是一种解决方法。 (除了dfr$date &lt;- with(dfr, ifelse(year == 2017, date17, date18)) 产生的结果完全相同。)

但我想要的是这个

> head(dfr, 4)
   id year some.vars     date17     date18       date
1 101 2017         7 2017-11-21 2018-11-21 2017-11-21
2 101 2018         0 2017-11-21 2018-11-21 2018-11-21
3 102 2017         3 2017-11-23 2018-11-23 2017-11-23
4 102 2018         5 2017-11-23 2018-11-23 2018-11-23

当我查看子集时,

d1 <- dfr$date17[dfr$year == 2017]
d2 <- dfr$date18[dfr$year == 2018]
> sapply(list(d1, d2), class)
     [,1]      [,2]     
[1,] "POSIXct" "POSIXct"
[2,] "POSIXt"  "POSIXt"

这并没有什么问题。由于 LHS 相似,我假设存在 &lt;- 分配问题。

我也尝试dfr[which(dfr["year"] == 2017), "date"] &lt;- dfr[which(dfr["year"] == 2017), "date17"] 来避免$ 符号(我是这样解释some points in this answer),但这种方法仍然没有成功。

那么如何在 base R 中将两个日期子集合并到数据框的一列中?

数据

> dput(dfr)
structure(list(id = c(101L, 101L, 102L, 102L, 103L, 103L, 104L, 
104L, 105L, 105L), year = c(2017L, 2018L, 2017L, 2018L, 2017L, 
2018L, 2017L, 2018L, 2017L, 2018L), some.vars = c(8L, 0L, 2L, 
9L, 6L, 3L, 4L, 0L, 9L, 4L), date17 = structure(c(1511218800, 
1511218800, 1511391600, 1511391600, 1511650800, 1511650800, 1511910000, 
1511910000, 1512169200, 1512169200), class = c("POSIXct", "POSIXt"
), tzone = ""), date18 = structure(c(1542754800, 1542754800, 
1542927600, 1542927600, 1543186800, 1543186800, 1543446000, 1543446000, 
1543705200, 1543705200), class = c("POSIXct", "POSIXt"), tzone = "")), class = "data.frame", row.names = c(NA, 
-10L))

> str(dfr)
'data.frame':   10 obs. of  5 variables:
 $ id       : int  101 101 102 102 103 103 104 104 105 105
 $ year     : int  2017 2018 2017 2018 2017 2018 2017 2018 2017 2018
 $ some.vars: int  1 2 8 6 2 0 1 2 4 1
 $ date17   : POSIXct, format: "2017-11-21" "2017-11-21" "2017-11-23" "2017-11-23" ...
 $ date18   : POSIXct, format: "2018-11-21" "2018-11-21" "2018-11-23" "2018-11-23" ...

【问题讨论】:

    标签: r


    【解决方案1】:

    两种快速解决方案,都与您如何创建 date 列有关。

    一个:

    dfr$date <- 0
    class(dfr$date) <- "Date"
    dfr$date[dfr$year == 2017] <- dfr$date17[dfr$year == 2017]
    dfr$date[dfr$year == 2018] <- dfr$date18[dfr$year == 2018]
    

    第二:

    dfr$date <- dfr$date17
    dfr$date[dfr$year == 2018] <- dfr$date18[dfr$year == 2018]
    

    因此,正如两种解决方案所暗示的那样,问题出在新列的类上。

    最后,在处理类似大小的情况时,可以简单地利用列的顺序

    dfr$date <- dfr[cbind(1:nrow(dfr), dfr$year - 2013)]
    

    【讨论】:

    • 嗯,我明白了。但是使用ifelse() 或更多时间它不会工作,不是吗?例如。 dfr$date &lt;- 'class&lt;-'(with(dfr, ifelse(year == 2017, date17, date18)), "Date") 失败。
    • 你的例子很有趣,即使ifelse(dfr$year == 2017, dfr$date17, dfr$date18) 失败了。 ?ifelse 讨论返回对象的类。
    • 你的cbind()trick 很聪明。不过,我可能有些案例会在明年重叠。
    【解决方案2】:

    当您创建日期列时,您正在创建一个数字列:

    dfr$date <- 0
    

    然后,当您分配后续日期数据时,它会被强制转换为数字格式。

    相反,从一个或其他现有日期列创建日期列,然后它从一开始就具有相同的类型。

    【讨论】:

      猜你喜欢
      • 2015-06-03
      • 2012-08-19
      • 2019-04-30
      • 2021-12-16
      • 1970-01-01
      • 2011-11-24
      • 2020-06-21
      • 1970-01-01
      • 2020-03-05
      相关资源
      最近更新 更多