【问题标题】:How to split a Date vector into k columns?如何将日期向量拆分为 k 列?
【发布时间】:2019-03-27 12:27:43
【问题描述】:

我有一个带日期的向量,例如

library("lubridate")
vec <- seq(ymd('1990-01-01'),ymd('1993-01-01'), by = '1 year')

我想分成 k 列。假设 k= 2,生成的数据框应该如下所示:

          X1         X2
1 1990-01-01 1992-01-01
2 1991-01-01 1993-01-01

第一个想法可能是这样的:

m <- matrix(vec, ncol= 2)

我知道这种方法是无效的,因为 matrix() 杀死了日期类:

m
     [,1] [,2]
[1,] 7305 8035
[2,] 7670 8401

不幸的是,data.frame() 没有 ncol 参数,并且在 data.frame() 中使用 matrix() 函数会导致上面显示的问题。对于这个看似简单的问题,我找不到任何解决方案,我很乐意得到帮助。

【问题讨论】:

  • 您希望列中的日期按顺序排列(如您的示例),还是随机排列,还是您没有偏好?
  • 我想按示例中的顺序排列日期。

标签: r date matrix vector


【解决方案1】:

日期在内部存储为数字,因此您可以在将它们转换为所需格式后将它们转换回来。

k <- 2
df <- data.frame(matrix(vec, ncol = k))
df[] <- lapply(df, as.Date, origin = "1970-01-01")

df
#          X1         X2
#1 1990-01-01 1992-01-01
#2 1991-01-01 1993-01-01

【讨论】:

  • 谢谢!我更喜欢 sindri_baldur 的解决方案,这就是为什么:在我的问题中,我使用 seq(..) 生成了 vec,因为它很方便。但实际上,我的向量类似于 vec
  • @igoR87 当然,如果您将as.Date 应用于POSIXct 类,它不会给您预期的输出。我使用了as.Date,因为您在输入中显示了日期。对于这个新向量,您需要使用as.POSIXct,例如df[] &lt;- lapply(df, as.POSIXct, origin = "1970-01-01", tz = "GMT") 不过,sindri_baldur 得到了很好的答案。
  • 是的,这是我的错误,我在尝试您的代码时注意到了这一点。我想提一下为什么我标记了 sindri_baldur 的答案 - 因为它似乎更笼统。
【解决方案2】:

您可以拆分为列表并将其转换为data.frame

k <- 2
df <- as.data.frame(split(vec, f = as.factor(rep(1:k, each = length(vec)/k))))

【讨论】:

    【解决方案3】:

    如果只有4个元素,那么做

    library(tibble)
    tibble(X1 = vec[1:2], X2 = vec[3:4])
    # A tibble: 2 x 2
    #  X1         X2        
    #   <date>     <date>    
    #1 1990-01-01 1992-01-01
    #2 1991-01-01 1993-01-01
    

    作为一般情况,

    library(dplyr)
    library(tidyr)
    k <- 2
    tibble(X1 = vec) %>%
       group_by(grp = paste0("X", as.integer(gl(n(), k, n())))) %>%
       mutate(ind = row_number()) %>%  
       spread(grp, X1) %>%        
       select(-ind)
    # A tibble: 2 x 2
    #  X1         X2        
    #  <date>     <date>    
    #1 1990-01-01 1992-01-01
    #2 1991-01-01 1993-01-01
    

    【讨论】:

      【解决方案4】:

      您可以计算中间是什么,然后创建两个日期序列。

      library("lubridate")
      
      StartDate <- ymd('1990-01-01')
      EndDate <- ymd('1993-01-01')
      MidDate <- StartDate + years(length(seq(StartDate,EndDate, by = '1 year'))/2)
      data.frame(X1 = seq(StartDate, MidDate - years(1), by = '1 year'),
                 X2 = seq(MidDate, EndDate, by = '1 year') )
      

      【讨论】:

      • 因此,如果 k 更改为 3,我将不得不手动输入类似 data.frame(X1 = seq(...), X2 = seq(...), X3= seq(. ..))?
      猜你喜欢
      • 2014-09-27
      • 2016-06-16
      • 1970-01-01
      • 2013-10-18
      • 2021-12-17
      • 2016-11-17
      • 2021-08-13
      相关资源
      最近更新 更多