如何对数据框的对角线求和
How to sum over diagonals of data frame
假设我有这个数据框:
1 2 3 4
100 8 12 5 14
99 1 6 4 3
98 2 5 4 11
97 5 3 7 2
在上面的数据框中,值表示 (100, 1), (99, 1)
等
中有多少观测值的计数
在我的上下文中,对角线具有相同的含义:
1 2 3 4
100 A B C D
99 B C D E
98 C D E F
97 D E F G
我如何对第一个数据框中的对角线求和(即,对相似字母的计数求和)?
这将产生:
group sum
A 8
B 13
C 13
D 28
E 10
F 18
G 2
例如D
就是5+5+4+14
您可以使用 row()
和 col()
来识别 row/column 关系。
m <- read.table(text="
1 2 3 4
100 8 12 5 14
99 1 6 4 3
98 2 5 4 11
97 5 3 7 2")
vals <- sapply(2:8,
function(j) sum(m[row(m)+col(m)==j]))
或(如?@thelatemail 的评论中所建议)
vals <- sapply(split(as.matrix(m), row(m) + col(m)), sum)
data.frame(group=LETTERS[seq_along(vals)],sum=vals)
或(@Frank)
data.frame(vals = tapply(as.matrix(m),
(LETTERS[row(m) + col(m)-1]), sum))
需要 as.matrix()
才能使 split()
正常工作...
这是一个使用 stack()
和 aggregate()
的解决方案,尽管它要求第二个 data.frame 包含字符向量,而不是因子(可以用 lapply(df2,as.character)
强制):
df1 <- data.frame(a=c(8,1,2,5), b=c(12,6,5,3), c=c(5,4,4,7), d=c(14,3,11,2) );
df2 <- data.frame(a=c('A','B','C','D'), b=c('B','C','D','E'), c=c('C','D','E','F'), d=c('D','E','F','G'), stringsAsFactors=F );
aggregate(sum~group,data.frame(sum=stack(df1)[,1],group=stack(df2)[,1]),sum);
## group sum
## 1 A 8
## 2 B 13
## 3 C 13
## 4 D 28
## 5 E 10
## 6 F 18
## 7 G 2
另一种解决方案使用 bgoldst 对 df1
和 df2
的定义
sapply(unique(c(as.matrix(df2))),
function(x) sum(df1[df2 == x]))
给予
#A B C D E F G
#8 13 13 28 10 18 2
(不是您想要的格式,但也许没问题...)
另一种 aggregate
变体,避免了公式界面,在这种情况下实际上使事情复杂化:
aggregate(list(Sum=unlist(dat)), list(Group=LETTERS[c(row(dat) + col(dat))-1]), FUN=sum)
# Group Sum
#1 A 8
#2 B 13
#3 C 13
#4 D 28
#5 E 10
#6 F 18
#7 G 2
假设我有这个数据框:
1 2 3 4
100 8 12 5 14
99 1 6 4 3
98 2 5 4 11
97 5 3 7 2
在上面的数据框中,值表示 (100, 1), (99, 1)
等
在我的上下文中,对角线具有相同的含义:
1 2 3 4
100 A B C D
99 B C D E
98 C D E F
97 D E F G
我如何对第一个数据框中的对角线求和(即,对相似字母的计数求和)?
这将产生:
group sum
A 8
B 13
C 13
D 28
E 10
F 18
G 2
例如D
就是5+5+4+14
您可以使用 row()
和 col()
来识别 row/column 关系。
m <- read.table(text="
1 2 3 4
100 8 12 5 14
99 1 6 4 3
98 2 5 4 11
97 5 3 7 2")
vals <- sapply(2:8,
function(j) sum(m[row(m)+col(m)==j]))
或(如?@thelatemail 的评论中所建议)
vals <- sapply(split(as.matrix(m), row(m) + col(m)), sum)
data.frame(group=LETTERS[seq_along(vals)],sum=vals)
或(@Frank)
data.frame(vals = tapply(as.matrix(m),
(LETTERS[row(m) + col(m)-1]), sum))
需要 as.matrix()
才能使 split()
正常工作...
这是一个使用 stack()
和 aggregate()
的解决方案,尽管它要求第二个 data.frame 包含字符向量,而不是因子(可以用 lapply(df2,as.character)
强制):
df1 <- data.frame(a=c(8,1,2,5), b=c(12,6,5,3), c=c(5,4,4,7), d=c(14,3,11,2) );
df2 <- data.frame(a=c('A','B','C','D'), b=c('B','C','D','E'), c=c('C','D','E','F'), d=c('D','E','F','G'), stringsAsFactors=F );
aggregate(sum~group,data.frame(sum=stack(df1)[,1],group=stack(df2)[,1]),sum);
## group sum
## 1 A 8
## 2 B 13
## 3 C 13
## 4 D 28
## 5 E 10
## 6 F 18
## 7 G 2
另一种解决方案使用 bgoldst 对 df1
和 df2
sapply(unique(c(as.matrix(df2))),
function(x) sum(df1[df2 == x]))
给予
#A B C D E F G
#8 13 13 28 10 18 2
(不是您想要的格式,但也许没问题...)
另一种 aggregate
变体,避免了公式界面,在这种情况下实际上使事情复杂化:
aggregate(list(Sum=unlist(dat)), list(Group=LETTERS[c(row(dat) + col(dat))-1]), FUN=sum)
# Group Sum
#1 A 8
#2 B 13
#3 C 13
#4 D 28
#5 E 10
#6 F 18
#7 G 2