У меня есть набор данных, который начинается в 1988 году и заканчивается в 2020 году. Я хочу создать средние значения для определенных интервалов времени. Например, 5 лет: 1988-1992, 1993-1997 и так далее. Но мне нужен новый столбец с этими средними значениями.
Например, предположим, что у меня есть это:
anos <- 1988:2020
valores <- c(15, 18, 20, NA, 25, 27, 28, NA, 32, 35, 36, 38, 40,
42, 45, 46, NA, 50, 52, 55, 56, 58, 60, NA, 65, 66,
68, 70, 72, 75, 76, 78, 80)
dataset <- data.frame(Ano = anos, Valor = valores)
Я хочу иметь это:
anos <- 1988:2020
valores <- c(15, 18, 20, NA, 25, 27, 28, NA, 32, 35, 36, 38, 40,
42, 45, 46, NA, 50, 52, 55, 56, 58, 60, NA, 65, 66,
68, 70, 72, 75, 76, 78, 80)
medias <- c(19.5, 19.5, 19.5, 19.5, 19.5,
30.5, 30.5, 30.5, 30.5, 30.5,
40.2, 40.2, 40.2, 40.2, 40.2,
50.75, 50.75, 50.75, 50.75, 50.75,
59.75, 59.75, 59.75, 59.75, 59.75,
70.2, 70.2, 70.2, 70.2, 70.2,
78, 78, 78)
dataset <- data.frame(Ano = anos, Valor = valores, Medias = medias)
Для каждого временного интервала имеются средние значения за пять лет, и среднее значение повторяется до следующих пяти лет. Последнее среднее значение представляет собой среднее из трех значений, поскольку общий период не кратен пяти.
Обновлено: также мне нужно будет использовать group_by()
.
Возьмите верхний остаток от деления на 5.
ave(
dataset$Valor,
ceiling(seq_along(rownames(dataset))/5),
FUN=function(x){mean(x,na.rm=T)}
)
Ano Valor Medias media
1 1988 15 19.50 19.50
2 1989 18 19.50 19.50
3 1990 20 19.50 19.50
4 1991 NA 19.50 19.50
5 1992 25 19.50 19.50
6 1993 27 30.50 30.50
7 1994 28 30.50 30.50
8 1995 NA 30.50 30.50
9 1996 32 30.50 30.50
10 1997 35 30.50 30.50
11 1998 36 40.20 40.20
12 1999 38 40.20 40.20
13 2000 40 40.20 40.20
14 2001 42 40.20 40.20
15 2002 45 40.20 40.20
16 2003 46 50.75 50.75
17 2004 NA 50.75 50.75
18 2005 50 50.75 50.75
19 2006 52 50.75 50.75
20 2007 55 50.75 50.75
21 2008 56 59.75 59.75
22 2009 58 59.75 59.75
23 2010 60 59.75 59.75
24 2011 NA 59.75 59.75
25 2012 65 59.75 59.75
26 2013 66 70.20 70.20
27 2014 68 70.20 70.20
28 2015 70 70.20 70.20
29 2016 72 70.20 70.20
30 2017 75 70.20 70.20
31 2018 76 78.00 78.00
32 2019 78 78.00 78.00
33 2020 80 78.00 78.00
База Р:
mean_every_n <- function(x, n=5L) {
grp <- (seq_along(x) - 1 ) %/% n
ave(x, grp, FUN = \(y) mean(y, na.rm = TRUE))
}
dataset$medias <- mean_every_5(dataset$Valor)
> head(dataset, 11)
# Ano Valor medias
# 1 1988 15 19.5
# 2 1989 18 19.5
# 3 1990 20 19.5
# 4 1991 NA 19.5
# 5 1992 25 19.5
# 6 1993 27 30.5
# 7 1994 28 30.5
# 8 1995 NA 30.5
# 9 1996 32 30.5
# 10 1997 35 30.5
# 11 1998 36 40.2
С помощью data.table
вы можете сделать следующее:
library(data.table)
setDT(dataset)[, Medias:=mean(Valor, na.rm=T), floor((Ano-3)/5)]
Выход:
Ano Valor Medias
<int> <num> <num>
1: 1988 15 19.50
2: 1989 18 19.50
3: 1990 20 19.50
4: 1991 NA 19.50
5: 1992 25 19.50
6: 1993 27 30.50
7: 1994 28 30.50
8: 1995 NA 30.50
9: 1996 32 30.50
10: 1997 35 30.50
11: 1998 36 40.20
12: 1999 38 40.20
13: 2000 40 40.20
14: 2001 42 40.20
15: 2002 45 40.20
16: 2003 46 50.75
17: 2004 NA 50.75
18: 2005 50 50.75
19: 2006 52 50.75
20: 2007 55 50.75
21: 2008 56 59.75
22: 2009 58 59.75
23: 2010 60 59.75
24: 2011 NA 59.75
25: 2012 65 59.75
26: 2013 66 70.20
27: 2014 68 70.20
28: 2015 70 70.20
29: 2016 72 70.20
30: 2017 75 70.20
31: 2018 76 78.00
32: 2019 78 78.00
33: 2020 80 78.00
Ano Valor Medias
Вот dplyr
версия:
library(dplyr)
n <- 5
dataset %>%
arrange(Ano) %>%
group_by(Group = floor((Ano - first(Ano))/n)) %>%
mutate(Medias = mean(Valor, na.rm = TRUE)) %>%
data.frame()
который возвращает следующее -
# Ano Valor Group Medias
#1 1988 15 0 19.50
#2 1989 18 0 19.50
#3 1990 20 0 19.50
#4 1991 NA 0 19.50
#5 1992 25 0 19.50
#6 1993 27 1 30.50
#7 1994 28 1 30.50
#8 1995 NA 1 30.50
#9 1996 32 1 30.50
#10 1997 35 1 30.50
#11 1998 36 2 40.20
#12 1999 38 2 40.20
#13 2000 40 2 40.20
#14 2001 42 2 40.20
#15 2002 45 2 40.20
#16 2003 46 3 50.75
#17 2004 NA 3 50.75
#18 2005 50 3 50.75
#19 2006 52 3 50.75
#20 2007 55 3 50.75
#21 2008 56 4 59.75
#22 2009 58 4 59.75
#23 2010 60 4 59.75
#24 2011 NA 4 59.75
#25 2012 65 4 59.75
#26 2013 66 5 70.20
#27 2014 68 5 70.20
#28 2015 70 5 70.20
#29 2016 72 5 70.20
#30 2017 75 5 70.20
#31 2018 76 6 78.00
#32 2019 78 6 78.00
#33 2020 80 6 78.00
В примере, которым вы поделились, у вас есть одна запись для каждого года и присутствуют данные за весь год, однако это также будет работать, когда:
Тай, это именно то, что я хотел.
@PedroCardoso Если вы ищете решение с использованием определенного пакета (в данном случае dplyr), лучше указать это и использовать соответствующий тег.
Использование cut
для создания группировки
library(dplyr)
dataset %>%
group_by(grp = cut(Ano, seq(min(Ano), max(Ano), 5), right=F)) %>%
mutate(medias = mean(Valor, na.rm=T)) %>%
ungroup() %>%
select(-grp)
# A tibble: 33 × 3
Ano Valor medias
<int> <dbl> <dbl>
1 1988 15 19.5
2 1989 18 19.5
3 1990 20 19.5
4 1991 NA 19.5
5 1992 25 19.5
6 1993 27 30.5
7 1994 28 30.5
8 1995 NA 30.5
9 1996 32 30.5
10 1997 35 30.5
# ℹ 23 more rows
# ℹ Use `print(n = ...)` to see more rows
Можешь попробовать
dataset %>%
mutate(grp = ceiling(row_number() / 5)) %>%
mutate(Medias = mean(Valor, na.rm = TRUE), .by = grp) %>%
select(-grp)
который дает
Ano Valor Medias
1 1988 15 19.50
2 1989 18 19.50
3 1990 20 19.50
4 1991 NA 19.50
5 1992 25 19.50
6 1993 27 30.50
7 1994 28 30.50
8 1995 NA 30.50
9 1996 32 30.50
10 1997 35 30.50
11 1998 36 40.20
12 1999 38 40.20
13 2000 40 40.20
14 2001 42 40.20
15 2002 45 40.20
16 2003 46 50.75
17 2004 NA 50.75
18 2005 50 50.75
19 2006 52 50.75
20 2007 55 50.75
21 2008 56 59.75
22 2009 58 59.75
23 2010 60 59.75
24 2011 NA 59.75
25 2012 65 59.75
26 2013 66 70.20
27 2014 68 70.20
28 2015 70 70.20
29 2016 72 70.20
30 2017 75 70.20
31 2018 76 78.00
32 2019 78 78.00
33 2020 80 78.00
Что, если в группе 5 есть только NA?