对 R 中数据帧的两个不同列执行 MAD 计算
Perform MAD calculation on two different columns of a dataframe in R
示例数据
date = seq(as.Date("2019/01/01"), by = "month", length.out = 48)
subproduct=rep("x",48)
actuals <- c(seq(1:29),rep(0,19))
m1 <- c(rep(0,24),seq(1:24))
m2<- c(rep(0,24),rep(10,24))
dfone <- data.frame(date,
subproduct,
actuals,m1,m2)
date subproduct actuals m1 m2
这是 dfone 的第 24-30 行
date subproduct actuals m1 m2
24 2020-12-01 x 24 0 0
25 2021-01-01 x 25 1 10
26 2021-02-01 x 26 2 10
27 2021-03-01 x 27 3 10
28 2021-04-01 x 28 4 10
29 2021-05-01 x 29 5 10
30 2021-06-01 x 0 6 10
我想做的是将此公式应用于所有三列(第 25-29 行)中数字不为 0 的行我想在第 25 行取实际值
m1abs1 <- abs(25-1)
m1abs2<- abs(26-2)
m1abs3 <- abs(27-3)
m1abs4 <- abs(28-4)
m1abs5 <- abs(29-5)
m1MAD <- sum(m1abs1,m1abs2,m1abs3,m1abs4,m1abs5)/5
# 24
m2abs1 <- abs(25-10)
m2abs2<- abs(26-10)
m2abs3 <- abs(27-10)
m2abs4 <- abs(28-10)
m2abs5 <- abs(29-10)
m2MAD <- sum(m2abs1,m2abs2,m2abs3,m2abs4,m2abs5)/5
# 17
max(m1MAD,m2MAD)
现在我们有了最大值,从数据框中删除不是最大值的列,因此在本例中为 m2MAD。
问题:在 R 中有没有更容易做到这一点的方法?
我们可以使用 if_all
到 filter
这些列中没有零的行,然后 summarise
到 return max
mean
的 abs
分离偏差
library(dplyr)
dfone %>%
filter(if_all(actuals:m2, ~ . != 0)) %>%
summarise(MADmax = max(mean(abs(actuals - m1)),
mean(abs(actuals - m2))))
-输出
MADmax
1 24
如果我们要删除不是 max
的列
dfone %>%
filter(if_all(actuals:m2, ~ . != 0)) %>%
summarise(nm1 = c('m1', 'm2')[which.max(c(mean(abs(actuals - m1)),
mean(abs(actuals - m2))))]) %>%
pull(nm1) %>% setdiff(names(dfone), .) -> tmp
dftwo <- dfone %>%
select(all_of(tmp))
或者另一种选择是
library(tidyr)
library(magrittr)
dfone %>%
filter(if_all(c(actuals, matches('^m\d+')), ~ . != 0)) %>%
summarise(across(matches('^m\d+'), ~ mean(abs(actuals - .)))) %>%
pivot_longer(everything()) %>%
filter(value != max(value)) %$%
select(dfone, -all_of(name))
或者使用 base R
与 subset
和 rowSums
来创建一个逻辑向量子集并得到 'MAD'
的 max
with(subset(dfone, !rowSums(dfone[c('actuals', 'm1', 'm2')] == 0)),
max(mean(abs(actuals - m1)),
mean(abs(actuals - m2))))
[1] 24
示例数据
date = seq(as.Date("2019/01/01"), by = "month", length.out = 48)
subproduct=rep("x",48)
actuals <- c(seq(1:29),rep(0,19))
m1 <- c(rep(0,24),seq(1:24))
m2<- c(rep(0,24),rep(10,24))
dfone <- data.frame(date,
subproduct,
actuals,m1,m2)
date subproduct actuals m1 m2
这是 dfone 的第 24-30 行
date subproduct actuals m1 m2
24 2020-12-01 x 24 0 0
25 2021-01-01 x 25 1 10
26 2021-02-01 x 26 2 10
27 2021-03-01 x 27 3 10
28 2021-04-01 x 28 4 10
29 2021-05-01 x 29 5 10
30 2021-06-01 x 0 6 10
我想做的是将此公式应用于所有三列(第 25-29 行)中数字不为 0 的行我想在第 25 行取实际值
m1abs1 <- abs(25-1)
m1abs2<- abs(26-2)
m1abs3 <- abs(27-3)
m1abs4 <- abs(28-4)
m1abs5 <- abs(29-5)
m1MAD <- sum(m1abs1,m1abs2,m1abs3,m1abs4,m1abs5)/5
# 24
m2abs1 <- abs(25-10)
m2abs2<- abs(26-10)
m2abs3 <- abs(27-10)
m2abs4 <- abs(28-10)
m2abs5 <- abs(29-10)
m2MAD <- sum(m2abs1,m2abs2,m2abs3,m2abs4,m2abs5)/5
# 17
max(m1MAD,m2MAD)
现在我们有了最大值,从数据框中删除不是最大值的列,因此在本例中为 m2MAD。
问题:在 R 中有没有更容易做到这一点的方法?
我们可以使用 if_all
到 filter
这些列中没有零的行,然后 summarise
到 return max
mean
的 abs
分离偏差
library(dplyr)
dfone %>%
filter(if_all(actuals:m2, ~ . != 0)) %>%
summarise(MADmax = max(mean(abs(actuals - m1)),
mean(abs(actuals - m2))))
-输出
MADmax
1 24
如果我们要删除不是 max
dfone %>%
filter(if_all(actuals:m2, ~ . != 0)) %>%
summarise(nm1 = c('m1', 'm2')[which.max(c(mean(abs(actuals - m1)),
mean(abs(actuals - m2))))]) %>%
pull(nm1) %>% setdiff(names(dfone), .) -> tmp
dftwo <- dfone %>%
select(all_of(tmp))
或者另一种选择是
library(tidyr)
library(magrittr)
dfone %>%
filter(if_all(c(actuals, matches('^m\d+')), ~ . != 0)) %>%
summarise(across(matches('^m\d+'), ~ mean(abs(actuals - .)))) %>%
pivot_longer(everything()) %>%
filter(value != max(value)) %$%
select(dfone, -all_of(name))
或者使用 base R
与 subset
和 rowSums
来创建一个逻辑向量子集并得到 'MAD'
max
with(subset(dfone, !rowSums(dfone[c('actuals', 'm1', 'm2')] == 0)),
max(mean(abs(actuals - m1)),
mean(abs(actuals - m2))))
[1] 24