R 中 SumIfs() 的向量
Vector of SumIfs() in R
我希望通过为每个观察创建条件平均值的均值-if 向量来模仿 Excel 在 R 中的 SumIfs() 函数。我见过很多使用 aggregate()
或 setDT()
来根据固定数量汇总数据框的示例。但是,我想根据数据框中每一行的可变输入创建这些摘要的向量。
这是我的数据示例:
> a <- c('c', 'a', 'b', 'a', 'c', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'b', 'a')
> b <- c(6, 1, 1, 2, 1, 2, 2, 4, 3, 3, 5, 5, 4, 6, 6)
> c <- c(69.9, 21.2, 37, 25, 65.9, 33.1, 67, 28.4, 36, 67, 22, 37.9, 62.3, 30, 25)
> df <- data.frame(cbind(a, b, c))
> df$b <- as.numeric(as.character(df$b))
> df$c <- as.numeric(as.character(df$c))
> df
a b c
1 c 6 69.9
2 a 1 21.2
3 b 1 37.0
4 a 2 25.0
5 c 1 65.9
6 b 2 33.1
7 c 2 67.0
8 a 4 28.4
9 b 3 36.0
10 c 3 67.0
11 a 5 22.0
12 b 5 37.9
13 c 4 62.3
14 b 6 30.0
15 a 6 25.0
我想添加第四列 df$d
,它对 df$a == x & y - 2 <= df$b < y
其中 x
和 y
的观察结果取 df$c
的平均值] 分别是 df$a
和 df$b
,用于计算观察值。
手动执行此操作,df$d
看起来像:
> df$d <- c(62.3, NA, NA, 21.2, NA, 37, 65.9, 25, 35.05, 66.45, 28.4, 36, 67, 37.9, 25.2)
> df
a b c d
1 c 6 69.9 62.30
2 a 1 21.2 NA
3 b 1 37.0 NA
4 a 2 25.0 21.20
5 c 1 65.9 NA
6 b 2 33.1 37.00
7 c 2 67.0 65.90
8 a 4 28.4 25.00
9 b 3 36.0 35.05
10 c 3 67.0 66.45
11 a 5 22.0 28.40
12 b 5 37.9 36.00
13 c 4 62.3 67.00
14 b 6 30.0 37.90
15 a 6 25.0 25.20
有没有可以自动执行此操作的功能?感谢您的帮助!
您可以使用一个循环来基本上准确地写出您对问题的描述:
n <- nrow(df)
d <- numeric(n)
for (i in seq_len(n)) {
x <- df$a[i]
y <- df$b[i]
d[i] <- with(df, mean(c[a == x & y - 2 <= b & b < y]))
}
all.equal(d, df$d)
#> [1] TRUE
我不喜欢这个解决方案,但我想不出一个简单的方法来做到这一点,因为由于 b
的条件,所需的分组不是不相交的。我很好奇是否有人想出更简洁的方法来做到这一点。
这可以使用 SQL 中的左 self-join 以简单的方式完成。这将连接到 df
的 u
实例的每一行 df
的 v
实例中满足 on
条件的那些行,然后对它们的 c
值。
library(sqldf)
sqldf("select u.*, avg(v.c) as d
from df u left join df v
on u.a = v.a and v.b between u.b-2 and u.b-1
group by u.rowid")
给予:
a b c d
1 c 6 69.9 62.30
2 a 1 21.2 NA
3 b 1 37.0 NA
4 a 2 25.0 21.20
5 c 1 65.9 NA
6 b 2 33.1 37.00
7 c 2 67.0 65.90
8 a 4 28.4 25.00
9 b 3 36.0 35.05
10 c 3 67.0 66.45
11 a 5 22.0 28.40
12 b 5 37.9 36.00
13 c 4 62.3 67.00
14 b 6 30.0 37.90
15 a 6 25.0 25.20
我希望通过为每个观察创建条件平均值的均值-if 向量来模仿 Excel 在 R 中的 SumIfs() 函数。我见过很多使用 aggregate()
或 setDT()
来根据固定数量汇总数据框的示例。但是,我想根据数据框中每一行的可变输入创建这些摘要的向量。
这是我的数据示例:
> a <- c('c', 'a', 'b', 'a', 'c', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'b', 'a')
> b <- c(6, 1, 1, 2, 1, 2, 2, 4, 3, 3, 5, 5, 4, 6, 6)
> c <- c(69.9, 21.2, 37, 25, 65.9, 33.1, 67, 28.4, 36, 67, 22, 37.9, 62.3, 30, 25)
> df <- data.frame(cbind(a, b, c))
> df$b <- as.numeric(as.character(df$b))
> df$c <- as.numeric(as.character(df$c))
> df
a b c
1 c 6 69.9
2 a 1 21.2
3 b 1 37.0
4 a 2 25.0
5 c 1 65.9
6 b 2 33.1
7 c 2 67.0
8 a 4 28.4
9 b 3 36.0
10 c 3 67.0
11 a 5 22.0
12 b 5 37.9
13 c 4 62.3
14 b 6 30.0
15 a 6 25.0
我想添加第四列 df$d
,它对 df$a == x & y - 2 <= df$b < y
其中 x
和 y
的观察结果取 df$c
的平均值] 分别是 df$a
和 df$b
,用于计算观察值。
手动执行此操作,df$d
看起来像:
> df$d <- c(62.3, NA, NA, 21.2, NA, 37, 65.9, 25, 35.05, 66.45, 28.4, 36, 67, 37.9, 25.2)
> df
a b c d
1 c 6 69.9 62.30
2 a 1 21.2 NA
3 b 1 37.0 NA
4 a 2 25.0 21.20
5 c 1 65.9 NA
6 b 2 33.1 37.00
7 c 2 67.0 65.90
8 a 4 28.4 25.00
9 b 3 36.0 35.05
10 c 3 67.0 66.45
11 a 5 22.0 28.40
12 b 5 37.9 36.00
13 c 4 62.3 67.00
14 b 6 30.0 37.90
15 a 6 25.0 25.20
有没有可以自动执行此操作的功能?感谢您的帮助!
您可以使用一个循环来基本上准确地写出您对问题的描述:
n <- nrow(df)
d <- numeric(n)
for (i in seq_len(n)) {
x <- df$a[i]
y <- df$b[i]
d[i] <- with(df, mean(c[a == x & y - 2 <= b & b < y]))
}
all.equal(d, df$d)
#> [1] TRUE
我不喜欢这个解决方案,但我想不出一个简单的方法来做到这一点,因为由于 b
的条件,所需的分组不是不相交的。我很好奇是否有人想出更简洁的方法来做到这一点。
这可以使用 SQL 中的左 self-join 以简单的方式完成。这将连接到 df
的 u
实例的每一行 df
的 v
实例中满足 on
条件的那些行,然后对它们的 c
值。
library(sqldf)
sqldf("select u.*, avg(v.c) as d
from df u left join df v
on u.a = v.a and v.b between u.b-2 and u.b-1
group by u.rowid")
给予:
a b c d
1 c 6 69.9 62.30
2 a 1 21.2 NA
3 b 1 37.0 NA
4 a 2 25.0 21.20
5 c 1 65.9 NA
6 b 2 33.1 37.00
7 c 2 67.0 65.90
8 a 4 28.4 25.00
9 b 3 36.0 35.05
10 c 3 67.0 66.45
11 a 5 22.0 28.40
12 b 5 37.9 36.00
13 c 4 62.3 67.00
14 b 6 30.0 37.90
15 a 6 25.0 25.20