如何根据一定的规则对矩阵中的列求和?

时间:2018-05-30 07:39:29

标签: r dataframe matrix

现在我有很多行数不同的矩阵。我想分别将奇数行和偶数行元素相加如下:

o <- matrix(rep(c(1,2,3,4,5,6),6),ncol = 6)
o2 <- matrix(rep(c(1,2,3,4,5,6),12),ncol = 6)   
#I want to sum the odd-number rows and even number rows element respectively
i=1
kg <- NULL
while(i <= 2){
op<-unlist(Map(sum,o[i,],o[i+2,],o[i+4,]))
kg <- c(kg,op)
i=i+1
}

i=1
kg2 <- NULL
while(i <= 2){
op2<-unlist(Map(sum,o2[i,],o2[i+2,],o2[i+4,],o2[i+6],o2[i+8],o2[i+10]))
kg2 <- c(kg2,op2)
i=i+1
}
kg
kg2 #the result should be a vector sequence like kg and kg2
> kg2
[1] 18 18 18 18 18 18 24 24 24 24 24 24

这是我能做的。但我的数据有很多不同长度的列。这是我能快速做到的任何方法吗?

我怎样才能产生类似&#34; o2 [i,],o2 [i + 2,],o2 [i + 4,],o2 [i + 6],o2 [i + 8] ,O2 [I + 10])&#34;根据输入的号码自动?谢谢你的帮助:))

2 个答案:

答案 0 :(得分:4)

也许是这样的?

o <- matrix(rep(c(1,2,3,4,5,6),6),ncol = 6)
o2 <- matrix(rep(c(1,2,3,4,5,6),12),ncol = 6)

even <- function(x) 2 * seq(1, nrow(x) / 2);
odd <- function(x) 2 * seq(1, nrow(x) / 2) - 1;

colSums(o[even(o), ]);
#[1] 12 12 12 12 12 12

colSums(o[odd(o), ]);
#[1] 9 9 9 9 9 9

colSums(o2[even(o2), ]);
#[1] 24 24 24 24 24 24

colSums(o2[odd(o2), ]);
#[1] 18 18 18 18 18 18

说明:even / odd返回matrix / data.frame的偶数/奇数行索引;然后我们可以使用colSums按列对项进行求和。

更新

要对行3, 6, 9, 12(或任何其他序列)中的条目求和,您只需要定义相应的函数,例如

another_seq <- function(x) 3 * seq(1, nrow(x) / 3)
colSums(o2[another_seq(o2), ]);
#[1] 18 18 18 18 18 18

答案 1 :(得分:2)

在OP循环中,如果我们想要更改Map以使其更自动

unlist(do.call(Map, c(f = sum, as.data.frame(t(o2[seq(i, i+10, by = 2),])))))

使用完整代码

o <- matrix(rep(c(1,2,3,4,5,6),6),ncol = 6)
o2 <- matrix(rep(c(1,2,3,4,5,6),12),ncol = 6)   
#I want to sum the odd-number rows and even number rows
i=1
kg <- NULL
while(i <= 2){
#op<-unlist(Map(sum,o[i,],o[i+2,],o[i+4,]))
op <- unlist(do.call(Map, c(f = sum, 
        as.data.frame(t(o[seq(i, i+4, by = 2),]))))) # change here

kg <- c(kg,op)
i=i+1
}

i=1
kg2 <- NULL
while(i <= 2){
#op2<-unlist(Map(sum,o2[i,],o2[i+2,],o2[i+4,],o2[i+6],o2[i+8],o2[i+10]))
op2 <- unlist(do.call(Map, c(f = sum, 
               s.data.frame(t(o2[seq(i, i+10, by = 2),]))))) # change here

kg2 <- c(kg2,op2)
i=i+1
}
kg
#[1]  9  9  9  9  9  9 12 12 12 12 12 12

kg2
#[1] 18 18 18 18 18 18 24 24 24 24 24 24

在OP的代码中,如果我们只用两个参数分析Map的个别参数,即&#39; o&#39;

的第一和第三行
i <- 1
Map(function(x, y) c(x, y),  o[i,], o[i+2,])
#[[1]]
#[1] 1 3

#[[2]]
#[1] 1 3

#[[3]]
#[1] 1 3

#[[4]]
#[1] 1 3

#[[5]]
#[1] 1 3

#[[6]]
#[1] 1 3

此处,list的每个元素都是连接的列值(c)。如果我们需要获得类似的结构,通过对奇数行进行子集化,我们转换行的子集,将其转换为data.frame,以便每个单独的块都是一列(对应于子行化的原始行)

do.call(Map, c(f=c, as.data.frame(t(o[c(i, i+2),]))))
#[[1]]
#V1 V2 
# 1  3 

#[[2]]
#V1 V2 
# 1  3 

#[[3]]
#V1 V2 
# 1  3 

#[[4]]
#V1 V2 
# 1  3 

#[[5]]
#V1 V2 
# 1  3 

#[[6]]
#V1 V2 
# 1  3 

将其保留为matrix无法解决问题,因为它将整个矩阵视为单个单元格(matrix是具有维度属性的vector

do.call(Map, c(f=c, o[c(i, i+2),]))
#[[1]]
#[1] 1 3 1 3 1 3 1 3 1 3 1 3

直接使用Map会循环遍历matrixvector)的每个元素,而不是每列

Map(c, o[c(i, i+2),]) # check the output

另一个选项是split col对象,然后执行sum

onew <- o[seq(i, i+4, by = 2),]
Map(sum, split(onew, col(onew)))

上面的方法是循环的,但我们也可以使用矢量化方法(就像在@Maurits Evers帖子中一样)。这里我们使用逻辑向量的循环来对行进行子集,然后执行seq

,而不是colSums
i1 <- c(TRUE, FALSE)
colSums(cbind(o[i1,], o[!i1,]))
#[1]  9  9  9  9  9  9 12 12 12 12 12 12

colSums(cbind(o2[i1,], o2[!i1,]))
#[1] 18 18 18 18 18 18 24 24 24 24 24 24
相关问题