Как разбить вектор даты на k столбцов?

#r #date #matrix #vector

#r #Дата #матрица #вектор

Вопрос:

У меня есть вектор с датами, например

 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, и использование функции matrix() внутри data.frame() приводит к проблеме, показанной выше. Я не смог найти никакого решения этого, казалось бы, простого вопроса, и я был бы рад помощи.

Комментарии:

1. Вы хотите, чтобы даты в ваших столбцах были расположены последовательно (как в вашем примере) или случайным образом, или у вас нет предпочтений?

2. Я хотел бы располагать даты в последовательности, как в примере.

Ответ №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
  

Комментарии:

1. Спасибо! Я предпочитаю решение sindri_baldur, и вот почему: в моем вопросе я сгенерировал vec с помощью seq (..), потому что это было удобно. Но на самом деле, мой вектор — это что-то вроде vec <- rep(dmy_hms(«01/01/2000 10:11:08»), 6). Применение вашего решения к моему фактическому вектору дало мне неправильные значения. Решение sindri_baldur не нуждается в какой-либо спецификации класса, что является преимуществом, и действительно, его решение сработало для меня.

2. @igoR87 определенно, это не даст вам ожидаемого результата, если вы подаете заявку as.Date в POSIXct класс. Я использовал as.Date , потому что вы указали даты в своих входных данных. Для этого нового вектора вам нужно использовать as.POSIXct , как df[] <- lapply(df, as.POSIXct, origin = "1970-01-01", tz = "GMT") Тем не менее, у sindri_baldur есть хороший ответ.

3. Да, это была моя ошибка, и я заметил это, когда попробовал ваш код. Я хотел упомянуть, почему я отметил ответ от sindri_baldur — baucause он кажется более общим.

Ответ №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') )
  

Комментарии:

1. Итак, если k изменится на 3, мне пришлось бы вручную вводить что-то вроде data.frame (X1 = seq (…), X2 = seq (…), X3 = seq (…))?