Как я могу рассчитать взвешенную скользящую среднюю концентрацию для каждого химического вещества по годам в определенном месте? - PullRequest
0 голосов
/ 31 января 2019

Я пытаюсь вычислить взвешенное скользящее среднее для каждой станции analyte_station.Я пытался сделать это несколькими способами в R, но продолжаю получать возвращаемые значения NA, и я не могу понять, почему.

Скользящая средняя будет рассчитываться на основе данных за предыдущие 5 лет (не включая текущий год) для каждой станции analyte_station.Весом будет количество образцов или столбец «Подсчет».

Таким образом, каждое «ANALYTE_STATION» будет иметь свое собственное средневзвешенное значение для каждого года.

Ошибка, которую я продолжаю получать: столбец Mean.5 должен иметь длину 1 (размер группы), а не35320

ИЛИ функция вернет значения NA для всего столбца

Я новичок в R и пробовал использовать библиотеки zoo и deplyr, а также функции lag, mutate и rollapply.

Распространенная ошибка, которую я продолжаю получать: столбец Mean.5 должен иметь длину 1 (размер группы), а не 35320

ИЛИ, функция будет возвращать значения NA для всего столбца.

dput(head(mean2))
structure(list(
YEAR_ANALYTE_STATION = c("2006 4,4'-DDD CCE-01", 
"2007 4,4'-DDD CCE-01", "2008 4,4'-DDD CCE-01", "2009 4,4'-DDD CCE-01", 
"2010 4,4'-DDD CCE-01", "2013 4,4'-DDD CCE-01"), 
Year = c(2006L, 
2007L, 2008L, 2009L, 2010L, 2013L), 
CCEMean = c(1.96969696966667, 
0.635237880333333, 10.108880584, 8.91217270166667, 18.54267311, 
1.409054917), Count = c("3", "3", "3", "3", "3", "3"), 
ANALYTE_STATION = 
c("4,4'-DDD CCE-01", "4,4'-DDD CCE-01", "4,4'-DDD CCE-01", "4,4'-DDD CCE- 
01", "4,4'-DDD CCE-01", "4,4'-DDD CCE-01")), 
row.names = c(NA, -6L), 
class = 
c("grouped_df", "tbl_df", "tbl", "data.frame"), 
vars = "ANALYTE_STATION", 
drop = TRUE, indices = list(0:5), group_sizes = 6L, biggest_group_size = 6L, 
labels = structure(list(ANALYTE_STATION = "4,4'-DDD CCE-01"), row.names = 
c(NA, -1L), class = "data.frame", vars = "ANALYTE_STATION", drop = TRUE))

head(mean2)
# A tibble: 6 x 5
# Groups:   ANALYTE_STATION [1]
YEAR_ANALYTE_STATION  Year CCEMean Count ANALYTE_STATION
<chr>                <int>   <dbl> <chr> <chr>          
1 2006 4,4'-DDD CCE-01  2006   1.97  3     4,4'-DDD CCE-01
2 2007 4,4'-DDD CCE-01  2007   0.635 3     4,4'-DDD CCE-01
3 2008 4,4'-DDD CCE-01  2008  10.1   3     4,4'-DDD CCE-01
4 2009 4,4'-DDD CCE-01  2009   8.91  3     4,4'-DDD CCE-01
5 2010 4,4'-DDD CCE-01  2010  18.5   3     4,4'-DDD CCE-01
6 2013 4,4'-DDD CCE-01  2013   1.41  3     4,4'-DDD CCE-01

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

скользящее среднее за предыдущие годы, не включая текущий год(например, 5 представляет среднее значение за 5 предыдущих лет)

mean5 = mean %>%
  mutate(Mean.lag1 = lag(Mean, n = 1)) %>%
  mutate(Mean.5.previous = rollapply(data = Mean.lag1, 
                                 width = 5, 
                                 FUN = mean, 
                                 align = "right", 
                                 fill = NA, 
                                 na.rm = T))

В конечном счете, каждое "ANALYTE_STATION" будет иметь свое собственное взвешенное среднее значение (из 5 предыдущих лет) для каждого года.

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Учитывая, что в вопросе говорится, что код в конце вопроса дает желаемый невзвешенный ответ, кажется, что то, что требуется, является средним значением предыдущих 5 строк кадра данных.На самом деле этот код не может быть корректным, поскольку 6 означает, что он производит все, должны быть NA, кроме последней, потому что только в последней строке есть 5 предыдущих строк;однако на самом деле этот код дает не-NA значение для 5-й строки, что неверно - это должно быть NA, так как до 5-й есть только 4 строки, а не 5.

Чтобы исправить это, попробуйтеследующий кодОбратите внимание на ?rollapply, что аргумент width может быть списком смещений из одного элемента, поэтому list(-seq(5)) означает предыдущие 5 элементов, а также обратите внимание, что вместо align="right" можно использовать rollapplyr с символом r в конце.В данных, показанных в вопросе, нет никаких NA в столбце CCEMean, и если это так, нам не нужен аргумент na.rm, хотя он не повредит.

mean2 %>%
  mutate(Mean5prev = rollapplyr(CCEMean, list(-seq(5)), mean, fill = NA, na.rm = TRUE))

Вопрос не точно определил, какие веса использовать, но это просто вопрос замены mean в приведенной выше функции функцией, которая вычисляет взвешенное среднее значение любым способом, который вы хотите.Для этого попробуйте использовать функцию weighted.mean.

0 голосов
/ 01 февраля 2019

Вы можете использовать пользовательскую функцию, которая вычисляет среднее значение за последние 5 лет, а не по строкам.

myRollmean <- function(x, tm, rge, excl.last=0) sapply(1:length(x), function(i) {
  period <- (tm[i] - rge - excl.last):(tm[i] - excl.last)
  return(mean(x[which(tm %in% period)]))
})

x обозначает столбец, который означает, что мы заинтересованы. tmэто столбец времени, rge диапазон времени, т. е. 5 лет в вашем случае, excl.last обозначает, сколько лет следует исключить.

df1$Mean.5 <- myRollmean(df1$CCEMean, df1$Year, 5)
df1$Mean.5.previous <- myRollmean(df1$CCEMean, df1$Year, 5, 1)

Результат

> df1
  YEAR_ANALYTE_STATION Year    CCEMean Count ANALYTE_STATION   Mean.5 Mean.5.previous
1 2006 4,4'-DDD CCE-01 2006  1.9696970     3 4,4'-DDD CCE-01 1.969697             NaN
2 2007 4,4'-DDD CCE-01 2007  0.6352379     3 4,4'-DDD CCE-01 1.302467        1.969697
3 2008 4,4'-DDD CCE-01 2008 10.1088806     3 4,4'-DDD CCE-01 4.237938        1.302467
4 2009 4,4'-DDD CCE-01 2009  8.9121727     3 4,4'-DDD CCE-01 5.406497        4.237938
5 2010 4,4'-DDD CCE-01 2010 18.5426731     3 4,4'-DDD CCE-01 8.033732        5.406497
6 2013 4,4'-DDD CCE-01 2013  1.4090549     3 4,4'-DDD CCE-01 9.743195        9.549741

Не могли бы вы проверить, дает ли функция желаемый результат?

Данные

mean2 <- structure(list(YEAR_ANALYTE_STATION = c("2006 4,4'-DDD CCE-01", 
"2007 4,4'-DDD CCE-01", "2008 4,4'-DDD CCE-01", "2009 4,4'-DDD CCE-01", 
"2010 4,4'-DDD CCE-01", "2013 4,4'-DDD CCE-01"), Year = c(2006L, 
2007L, 2008L, 2009L, 2010L, 2013L), CCEMean = c(1.96969696966667, 
0.635237880333333, 10.108880584, 8.91217270166667, 18.54267311, 
1.409054917), Count = c("3", "3", "3", "3", "3", "3"), ANALYTE_STATION = c("4,4'-DDD CCE-01", 
"4,4'-DDD CCE-01", "4,4'-DDD CCE-01", "4,4'-DDD CCE-01", "4,4'-DDD CCE-01", 
"4,4'-DDD CCE-01")), row.names = c(NA, -6L), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"), vars = "ANALYTE_STATION", drop = TRUE, indices = list(
    0:5), group_sizes = 6L, biggest_group_size = 6L, labels = structure(list(
    ANALYTE_STATION = "4,4'-DDD CCE-01"), row.names = c(NA, -1L
), class = "data.frame", vars = "ANALYTE_STATION", drop = TRUE))

df1 <- as.data.frame(mean2)
...