2016-10-20 14 views
3

Я пытаюсь настроить набор данных панели для создания новой переменной, используя средние значения регулярных периодов времени ожидания. Мой пример набор данных выглядеть, как показано ниже, и можно получить с помощью ниже кодовКак получить среднее значение периода задержки в частоте как новую переменную в r

 Time ID Value1 Value2 
1 Jan-14 A  12  NA 
2 Feb-14 A  14  NA 
3 Mar-14 A  15  NA 
4 Apr-14 A  18  NA 
5 May-14 A  10  NA 
6 Jun-14 A  12 13.67 
7 Jul-14 A  13 15.67 
8 Aug-14 A  14 14.33 
9 Jan-14 B  32  NA 
10 Feb-14 B  14  NA 
11 Mar-14 B  15  NA 
12 Apr-14 B  18  NA 
13 May-14 B  20  NA 
14 Jun-14 B  12 20.33 
15 Jul-14 B  13 15.67 
16 Aug-14 B  14 17.78 

df<-structure(list(Time = structure(c(4L, 3L, 7L, 1L, 8L, 6L, 5L, 
2L, 4L, 3L, 7L, 1L, 8L, 6L, 5L, 2L), .Label = c("Apr-14", "Aug-14", 
"Feb-14", "Jan-14", "Jul-14", "Jun-14", "Mar-14", "May-14"), class = "factor"), 
    ID = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A", "B"), class = "factor"), 
    Value1 = c(12L, 14L, 15L, 18L, 10L, 12L, 13L, 14L, 32L, 14L, 
    15L, 18L, 20L, 12L, 13L, 14L)), .Names = c("Time", "ID", 
"Value1"), class = "data.frame", row.names = c(NA, -16L)) 

Я хочу создать новую переменную с именем Value2 учитывая среднем 3 месяца, соответствующие предыдущим четвёртым-6-го месяца для каждого наблюдения (это просто например, мой ежемесячный набор данных рассчитан на 12 лет на 40 человек, а также я должен рассмотреть более высокий уровень отставания, чем 3 месяца, возможно, 14 месяцев). Здесь мне нужно также рассмотреть ID, потому что необходимо сохранить структуру панели. Для всех наблюдений, которые не были полными 3 месяца назад, должно указываться как NA. Например, Jun_14_A должно получить среднее значение от Mar_14_A до Jan_14_A. (12 + 14 + 15)/3 = 13,67

Я привел несколько примеров here, но они не обеспечивают то, что я ищу специально для средних средних значений и обозначают как NA, если нет предыдущих трех полных месяцев.

Заранее спасибо за любую помощь

ответ

2

Вот еще один способ, используя только data.table и это shift функция в сочетании с Reduce (Это почти контратип this)

library(data.table) 
setDT(df)[, Value2 := Reduce(`+`, shift(Value1, 3:5))/3, by = ID] 
df 
#  Time ID Value1 Value2 
# 1: Jan-14 A  12  NA 
# 2: Feb-14 A  14  NA 
# 3: Mar-14 A  15  NA 
# 4: Apr-14 A  18  NA 
# 5: May-14 A  10  NA 
# 6: Jun-14 A  12 13.66667 
# 7: Jul-14 A  13 15.66667 
# 8: Aug-14 A  14 14.33333 
# 9: Jan-14 B  32  NA 
# 10: Feb-14 B  14  NA 
# 11: Mar-14 B  15  NA 
# 12: Apr-14 B  18  NA 
# 13: May-14 B  20  NA 
# 14: Jun-14 B  12 20.33333 
# 15: Jul-14 B  13 15.66667 
# 16: Aug-14 B  14 17.66667 
1

Один из способов сделать это, это не рафинированное, так может быть, кто-то (меня, если я получаю время) позже приду с более элегантным решением:
Первого, что нужно конвертируйте df$time в фактическую дату.

library(zoo) 
df$Time=as.yearmon(as.character(df$Time),"%b-%y") 
library(dplyr) 
df%>% 
    group_by(ID)%>% 
    mutate(Value2 = (lag(Value1, 3) + lag(Value1, 4) + lag(Value1, 5))/3) 

    Time  ID Value1 Value2 
    <fctr> <fctr> <int> <dbl> 
1 Jan-14  A  12  NA 
2 Feb-14  A  14  NA 
3 Mar-14  A  15  NA 
4 Apr-14  A  18  NA 
5 May-14  A  10  NA 
6 Jun-14  A  12 13.66667 
7 Jul-14  A  13 15.66667 
8 Aug-14  A  14 14.33333 
9 Jan-14  B  32  NA 
10 Feb-14  B  14  NA 
11 Mar-14  B  15  NA 
12 Apr-14  B  18  NA 
13 May-14  B  20  NA 
14 Jun-14  B  12 20.33333 
15 Jul-14  B  13 15.66667 
16 Aug-14  B  14 17.66667 

Я создал 3 переменные с лагом 3, 4 и 5 и просто вычислить среднее, любое NA (не 3 полных месяцев) возвратит NA.

+0

Спасибо за эти ответы. Все отлично работает с моим набором данных. Но я выбираю ответ таблицы данных со сдвигом и уменьшением. – sriya

+0

Предложите 'mutate (Value2 = (lag (Value1, 3) + lag (Value1, 4) + lag (Value1, 5))/3)', в этом случае 'select' не требуется. –

+0

Хорошее предложение, я отредактировал. – Haboryme

1

Мы могли бы попробовать:

library(data.table) 
setDT(df) 
f <- function(x) if(anyNA(x[1:6])) NA else mean(x[1:3]) 
df[, Value2 := zoo::rollapply(Value1, 6, f, align = "right", partial = TRUE), by = ID] 

> df 
     Time ID Value1 Value2 
1: Jan-14 A  12  NA 
2: Feb-14 A  14  NA 
3: Mar-14 A  15  NA 
4: Apr-14 A  18  NA 
5: May-14 A  10  NA 
6: Jun-14 A  12 13.66667 
7: Jul-14 A  13 15.66667 
8: Aug-14 A  14 14.33333 
9: Jan-14 B  32  NA 
10: Feb-14 B  14  NA 
11: Mar-14 B  15  NA 
12: Apr-14 B  18  NA 
13: May-14 B  20  NA 
14: Jun-14 B  12 20.33333 
15: Jul-14 B  13 15.66667 
16: Aug-14 B  14 17.66667 
+0

Я изучаю новую функцию здесь rollapply. благодаря – sriya

2

Попробуйте rollapplyr из зоопарка. Ширина list(-3:-5) означает, что она будет использовать компоненты, которые смещены -3, -4 и -5 от текущей точки на каждой итерации:

library(zoo) 
roll <- function(x) rollapplyr(x, list(-3:-5), mean, fill = NA) 
transform(df, Value2 = ave(Value1, ID, FUN = roll)) 

дает следующий кадр данных:

 Time ID Value1 Value2 
1 Jan-14 A  12  NA 
2 Feb-14 A  14  NA 
3 Mar-14 A  15  NA 
4 Apr-14 A  18  NA 
5 May-14 A  10  NA 
6 Jun-14 A  12 13.66667 
7 Jul-14 A  13 15.66667 
8 Aug-14 A  14 14.33333 
9 Jan-14 B  32  NA 
10 Feb-14 B  14  NA 
11 Mar-14 B  15  NA 
12 Apr-14 B  18  NA 
13 May-14 B  20  NA 
14 Jun-14 B  12 20.33333 
15 Jul-14 B  13 15.66667 
16 Aug-14 B  14 17.66667 

Примечание: Хотя мы не внесли изменения, так как не нужно отвечать на вопрос, обратите внимание, что вы можете использовать класс "yearmon" zoo для первого столбца. Значения года/месяца этого класса сортируются правильно, но хорошо отображаются. То есть

transform(df, Time = as.yearmon(Time, "%b-%y"), Value2 = ...as above...)