Использование соответствия по нескольким критериям для генерации значения в R - PullRequest
1 голос
/ 06 января 2020

В настоящее время у меня есть следующий формат данных:

df = data.frame(c(rep("A", 12), rep("B", 12)), rep(1:12, 2), seq(-12, 11))
colnames(df) = c("station", "month", "mean")
df

df_master = data.frame(c(rep("A", 10), rep("B", 10)), rep(c(27:31, 1:5), 2), rep(c(rep(1, 5), rep(2, 5)), 2), rep(seq(-4,5), 2))
colnames(df_master) = c("station", "day", "month", "value")
df_master

Фактически df - это среднемесячное значение для каждой станции, и я хочу вычислить новую переменную в наборе данных df_master, которая вычисляет разницу от месячной среднее значение для каждого ежедневного наблюдения. Мне удалось сделать это с помощью общего среднего значения, включающего все данные, но поскольку средние значения различаются для каждой станции, поэтому я хотел бы указать новую переменную станцию, указав c.

. Я попробовал следующее код для соответствия месячному значению, но в настоящее время он не учитывает различия между станциями:

df_master$mean = df$mean[match(df_master$month, df$month)]
df_master = df_master %>% mutate(diff = value - mean)

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

Ответы [ 3 ]

2 голосов
/ 06 января 2020

С dplyr с использованием левого соединения

library(dplyr)
left_join(df_master, df, by = c('station', 'month')) %>% 
        mutate(monthdiff  = value - mean) %>%
        select(-mean)
2 голосов
/ 06 января 2020

Если вы преобразуете их в data.tables, вы можете добавить столбец различий с помощью соединения обновления, объединяя df_master с df при условии, что значения для station и month равны.

library(data.table)
setDT(df_master)
setDT(df)

df_master[df, on = .(station, month), 
          diff_monthmean := value - i.mean]

df_master
#     station day month value diff_monthmean
#  1:       A  27     1    -4              8
#  2:       A  28     1    -3              9
#  3:       A  29     1    -2             10
#  4:       A  30     1    -1             11
#  5:       A  31     1     0             12
#  6:       A   1     2     1             12
#  7:       A   2     2     2             13
#  8:       A   3     2     3             14
#  9:       A   4     2     4             15
# 10:       A   5     2     5             16
# 11:       B  27     1    -4             -4
# 12:       B  28     1    -3             -3
# 13:       B  29     1    -2             -2
# 14:       B  30     1    -1             -1
# 15:       B  31     1     0              0
# 16:       B   1     2     1              0
# 17:       B   2     2     2              1
# 18:       B   3     2     3              2
# 19:       B   4     2     4              3
# 20:       B   5     2     5              4
1 голос
/ 06 января 2020

Другой вариант может быть:

transform(df_master, 
          diff = value - merge(df_master, df, by = c('station', 'month'), all.x = TRUE)$mean)

Или, используя match с interaction

transform(df_master, 
diff = value - df$mean[match(interaction(df_master[c("month", "station")]), interaction(df[c("month", "station")]))])
...