#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 (…))?