#r #dplyr #tidyr
#r #dplyr #tidyr
Вопрос:
Я пытаюсь перекодировать некоторые данные, собранные каждые 2 часа, таким образом, чтобы я находил начальную точку для каждого идентификатора (т. Е. Когда obs не равен нулю, т. Е. Есть Данные для этого момента времени), назовите это время 0, а затем для каждого последующего момента времени вызывается 2, 4, 6 и т.д.
Например,
ID <- c("f1", "f1", "f1", "f1", "f2", "f2", "f2", "f2", "f3", "f3", "f3", "f3")
time <- rep(c(66, 68, 70, 72), 3)
obs <- c(1, 3, 5, 6, 0, 0, 3, 4, 0, 1, 3, 3)
new.time <- c(0, 2, 4, 6, NA, NA, 0, 2, NA, 0, 2, 4)
data <- as.data.frame(cbind(ID, time, obs, new.time))
Надеюсь, этот фрейм данных работает
у меня есть идентификатор, время и obs, но я хочу создать «новое время» — любая помощь приветствуется, особенно решение dplyr
Комментарии:
1. ок, изменились на фрейм данных
Ответ №1:
1) Мы определяем data
как data.frame, а не как матрицу в примечании в конце, а затем используем ave
для установки new.time
:
Пакеты не используются.
make_no <- function(obs) c(rep(NA, sum(obs == 0)), seq(0, length = sum(obs != 0), by = 2))
transform(data, new.time = ave(obs, ID, FUN = make_no))
предоставление:
ID time obs new.time
1 f1 66 1 0
2 f1 68 3 2
3 f1 70 5 4
4 f1 72 6 6
5 f2 66 0 NA
6 f2 68 0 NA
7 f2 70 3 0
8 f2 72 4 2
9 f3 66 0 NA
10 f3 68 1 0
11 f3 70 3 2
12 f3 72 3 4
2) или с помощью dplyr:
data %>%
group_by(ID) %>%
mutate(new.time = make_no(obs)) %>%
ungroup
Примечание
ID <- c("f1", "f1", "f1", "f1", "f2", "f2", "f2", "f2", "f3", "f3", "f3", "f3")
time <- rep(c(66, 68, 70, 72), 3)
obs <- c(1, 3, 5, 6, 0, 0, 3, 4, 0, 1, 3, 3)
data <- data.frame(ID, time, obs)
Комментарии:
1. спасибо, это работает с практическим набором данных, но не с фактическим набором данных… я просто получаю NAs….
2. Обратите внимание, что в коде, представленном в вопросе, есть ошибка.
as.data.frame(cbind(...))
создает символьную матрицу, а затем преобразует ее во фрейм данных. В результате столбцы, которые должны быть числовыми, являются коэффициентами. Смотрите Примечание в конце ответа для правильного способа сделать это. Кроме этого, вам нужно либо выяснить, в чем разница между тем, что у вас есть, и тем, что вы представили, и исправить вопрос, поскольку мы не можем знать, что у вас есть, но не показали.
Ответ №2:
Мы можем создать пользовательскую функцию и применить ее к группе, т.е.
f1 <- function(x) {
x1 <- length(x[x != 0])
i1 <- seq(0, length.out = x1, by = 2)
i2 <- c(rep(NA, (length(x) - x1)),i1)
return(i2)
}
#Using `dplyr` to apply it,
library(dplyr)
df %>%
group_by(ID) %>%
mutate(new = f1(obs))
что дает,
# A tibble: 12 x 4 # Groups: ID [3] ID time obs new <fct> <fct> <fct> <dbl> 1 f1 66 1 0 2 f1 68 3 2 3 f1 70 5 4 4 f1 72 6 6 5 f2 66 0 NA 6 f2 68 0 NA 7 f2 70 3 0 8 f2 72 4 2 9 f3 66 0 NA 10 f3 68 1 0 11 f3 70 3 2 12 f3 72 3 4