Внутри для l oop возьмите 1-й и 5-й элемент en каждый l oop? - PullRequest
1 голос
/ 22 февраля 2020

Я пытаюсь создать фрейм данных с началом и концом для диапазонов дат 5 дней.

Это моя функция, которую я использую для создания списка диапазонов дат:

from <- as.Date("2017-01-01")
to <- as.Date("2020-02-21")
d <- seq(from, to, by = "1 days")
n <- length(d)
chunk <- 5
f <- rep(1:((n %/% chunk) + 1), each = chunk, length.out = n)
head(split(d, f))

Элементы выглядят следующим образом:

head(split(d, f), 4)
$`1`
[1] "2017-01-01" "2017-01-02" "2017-01-03" "2017-01-04" "2017-01-05"

$`2`
[1] "2017-01-06" "2017-01-07" "2017-01-08" "2017-01-09" "2017-01-10"

$`3`
[1] "2017-01-11" "2017-01-12" "2017-01-13" "2017-01-14" "2017-01-15"

$`4`
[1] "2017-01-16" "2017-01-17" "2017-01-18" "2017-01-19" "2017-01-20"

Мне нужно взять 1-ю и 5-ю дату каждого элемента списка, чтобы создать фрейм данных. Я пытаюсь сделать для l oop, чтобы захватить начало (1-й элемент) и конец (5-й элемент).

Я пытаюсь получить к ним доступ следующим образом:

my_date_ranges <- split(d, f)

my_date_ranges[[1]][1] #first element start
my_date_ranges[[1]][5] #first element end
my_date_ranges[[2]][1] #second element start
my_date_ranges[[2]][5] #second element end
...

Но когда я пытаюсь l oop список вот так:

for(i in my_date_ranges){
  print(my_date_ranges[[i]][1]) #this would be the starts
}

я получаю эту ошибку:

Ошибка в my_date_ranges [[i]]: нет такой индекс на уровне 1

Желаемый вывод:

starts       ends
1  2017-01-01 2017-01-05
2  2017-01-06 2017-01-10
3  2017-01-11 2017-01-15
...
n  2020-02-17 today-minus-1-day  

1 Ответ

1 голос
/ 22 февраля 2020

Мы можем использовать lapply до l oop над list, выбрать 1-й элемент как «начало», 5-й как «конец», чтобы создать «data.frame

out <- do.call(rbind, lapply(split(d, f), function(x) 
        data.frame(start = x[1], end = x[5])))

head(out)
#    start        end
#1 2017-01-01 2017-01-05
#2 2017-01-06 2017-01-10
#3 2017-01-11 2017-01-15
#4 2017-01-16 2017-01-20
#5 2017-01-21 2017-01-25
#6 2017-01-26 2017-01-30



str(out)
#'data.frame':  230 obs. of  2 variables:
#$ start: Date, format: "2017-01-01" "2017-01-06" "2017-01-11" ...
#$ end  : Date, format: "2017-01-05" "2017-01-10" "2017-01-15" ...

»

Или другой вариант - вместо вызова data.frame внутри каждого элемента list, извлеките 'Date' отдельно и затем выполните окончательный data.frame

lst1 <- split(d, f)    
out1 <- data.frame(start = do.call(c, lapply(lst1, `[`, 1)), 
            end = do.call(c, lapply(lst1, `[`, 5)))

i1 <- is.na(out1$end)
out1$end[i1] <- out1$start[i1]

Или, если OP хотел получить элемент last, если элементов меньше

i1 <- lengths(lst1) < 5
out1$end[i1] <-  do.call(c, lapply(lst1[i1], tail, 1))

Если мы используем код OP, одним из вариантов будет инициализация list или data.frame с NA, а затем обновлять объект на каждом l oop run

out2 <- as.data.frame(matrix(NA, nrow = length(my_date_ranges),
       ncol = 2, dimnames = list(NULL, c("start", "end"))))

for(i in seq_along(my_date_ranges)) {

    out2$start[i] <- list(my_date_ranges[[i]][1])
    out2$end[i] <- list(my_date_ranges[[i]][5])
 }
out2$start <- do.call(c, out2$start)
out2$end <- do.call(c, out2$end)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...