在 R 中使用矢量化创建新矩阵
Creating a new matrix using vectorization in R
我有两个矩阵 'times' 和 'scaleFactor'。 'times' 矩阵中的每一行代表一个人,该列代表某个事件发生的时间。该事件会更改放大系数,可在 'scaleFactor' 矩阵中找到。例如,对于第 1 个人,时间间隔 (1,3).
中的因子为 1.2
我想创建一个在每个整数时间点都有因子的矩阵 C,其中第一列是时间 = 0。我写了生成矩阵'C'的代码,但我想知道是否可以避免'for'循环,因为实际矩阵非常大
scaleFactor <- matrix(c(1,1.1,1.2,1.4,
1,1.3,1.4,1.6,
1,1.2,1.6,2.1),nrow = 3,ncol = 4, byrow = T)
times <- matrix(c(0,1,3,99,
0,2,5,99,
0,1,4,99),nrow = 3,ncol = 4,byrow = T)
> scaleFactor
[,1] [,2] [,3] [,4]
[1,] 1 1.1 1.2 1.4
[2,] 1 1.3 1.4 1.6
[3,] 1 1.2 1.6 2.1
> times
[,1] [,2] [,3] [,4]
[1,] 0 1 3 99
[2,] 0 2 5 99
[3,] 0 1 4 99
C <- matrix(0,nrow = 3,ncol = 6)
for (i in 1:ncol(C)){
indices <- max.col(i-1<=times,'first')
C[,i] <- scaleFactor[cbind(1:3,indices)]
}
> C
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1.1 1.2 1.2 1.4 1.4
[2,] 1 1.3 1.3 1.4 1.4 1.4
[3,] 1 1.2 1.6 1.6 1.6 2.1
非常感谢您的帮助。
编辑:我后来意识到 'times' 矩阵可以有非整数时间值。对于这种情况,akrun 建议的方法有效。谢谢!
times2 <- matrix(c(0,1.2,3.6,99,
0,2.1,5.3,99,
0,1,4,99),nrow = 3,ncol = 4,byrow = T)
> times2
[,1] [,2] [,3] [,4]
[1,] 0 1.2 3.6 99
[2,] 0 2.1 5.3 99
[3,] 0 1.0 4.0 99
# Matrix C would be -
> C
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1.1 1.2 1.2 1.4 1.4
[2,] 1 1.3 1.3 1.4 1.4 1.4
[3,] 1 1.2 1.6 1.6 1.6 2.1
这是 rep
在纯 Vectorized
代码中拼接的一种方法
- 我们
rep
将C(减去1)的列序列与'times' 的length
联系起来
- 对
t
ransposed 'times' 进行比较
- 转换为
matrix
以创建 dim
属性
- 应用
max.col
获取每行最大值的列索引
- 然后,
cbind
与行索引
- 从5
根据row/column索引得到对应的'scaleFactor'值
- 使用
[]
将输出分配回 C,以便保留矩阵属性
C[] <- scaleFactor[cbind(1:3, max.col(matrix(rep(seq_len(ncol(C)) - 1,
each = length(times)) <= c(t(times)), ncol = ncol(times),
byrow = TRUE), "first"))]
-输出
C
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1.1 1.2 1.2 1.4 1.4
[2,] 1 1.3 1.3 1.4 1.4 1.4
[3,] 1 1.2 1.6 1.6 1.6 2.1
我们可以使用 rep
和 asplit
的技巧(将数组拆分为向量列表,在这里很方便)。
C <- t(
mapply(rep, asplit(scaleFactor,1),
times = asplit(cbind(1, t(apply(times, 1, diff))), 1))
)
dim(C)
# [1] 3 100
C[,1:8]
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
# [1,] 1 1.1 1.2 1.2 1.4 1.4 1.4 1.4
# [2,] 1 1.3 1.3 1.4 1.4 1.4 1.6 1.6
# [3,] 1 1.2 1.6 1.6 1.6 2.1 2.1 2.1
它的稳定性取决于times
的最后一列是否相等(这样所有的人迭代相同的时间段数)。
首先将 times
(发生变化的时间段)转换为“持续时间”(每列中的天数),
cbind(1, t(apply(times, 1, diff)))
# [,1] [,2] [,3] [,4]
# [1,] 1 1 2 96
# [2,] 1 2 3 94
# [3,] 1 1 3 95
从那里,我们使用这些数字作为 rep
的 times=
参数。为了保持维度正确,我们为每个人独立地做这件事,这就是为什么我们需要使用 asplit(., 1)
:
按行拆分矩阵
asplit(scaleFactor, 1)
# [[1]]
# [1] 1.0 1.1 1.2 1.4
# [[2]]
# [1] 1.0 1.3 1.4 1.6
# [[3]]
# [1] 1.0 1.2 1.6 2.1
然后我们将比例因子与相应的时间配对成rep
:
head(
rep(c(1, 1.1, 1.2, 1.4), times = c(1, 1, 2, 96)),
8)
# [1] 1.0 1.1 1.2 1.2 1.4 1.4 1.4 1.4
为了同时有效地遍历两个矩阵的所有行,我们 asplit
矩阵并将它们输入 mapply
,它传递了 [=24= 的第一行] 与我们的“持续时间”的第一行(times
不同),第二行与第二行等
我有两个矩阵 'times' 和 'scaleFactor'。 'times' 矩阵中的每一行代表一个人,该列代表某个事件发生的时间。该事件会更改放大系数,可在 'scaleFactor' 矩阵中找到。例如,对于第 1 个人,时间间隔 (1,3).
中的因子为 1.2我想创建一个在每个整数时间点都有因子的矩阵 C,其中第一列是时间 = 0。我写了生成矩阵'C'的代码,但我想知道是否可以避免'for'循环,因为实际矩阵非常大
scaleFactor <- matrix(c(1,1.1,1.2,1.4,
1,1.3,1.4,1.6,
1,1.2,1.6,2.1),nrow = 3,ncol = 4, byrow = T)
times <- matrix(c(0,1,3,99,
0,2,5,99,
0,1,4,99),nrow = 3,ncol = 4,byrow = T)
> scaleFactor
[,1] [,2] [,3] [,4]
[1,] 1 1.1 1.2 1.4
[2,] 1 1.3 1.4 1.6
[3,] 1 1.2 1.6 2.1
> times
[,1] [,2] [,3] [,4]
[1,] 0 1 3 99
[2,] 0 2 5 99
[3,] 0 1 4 99
C <- matrix(0,nrow = 3,ncol = 6)
for (i in 1:ncol(C)){
indices <- max.col(i-1<=times,'first')
C[,i] <- scaleFactor[cbind(1:3,indices)]
}
> C
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1.1 1.2 1.2 1.4 1.4
[2,] 1 1.3 1.3 1.4 1.4 1.4
[3,] 1 1.2 1.6 1.6 1.6 2.1
非常感谢您的帮助。
编辑:我后来意识到 'times' 矩阵可以有非整数时间值。对于这种情况,akrun 建议的方法有效。谢谢!
times2 <- matrix(c(0,1.2,3.6,99,
0,2.1,5.3,99,
0,1,4,99),nrow = 3,ncol = 4,byrow = T)
> times2
[,1] [,2] [,3] [,4]
[1,] 0 1.2 3.6 99
[2,] 0 2.1 5.3 99
[3,] 0 1.0 4.0 99
# Matrix C would be -
> C
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1.1 1.2 1.2 1.4 1.4
[2,] 1 1.3 1.3 1.4 1.4 1.4
[3,] 1 1.2 1.6 1.6 1.6 2.1
这是 rep
在纯 Vectorized
代码中拼接的一种方法
- 我们
rep
将C(减去1)的列序列与'times' 的 - 对
t
ransposed 'times' 进行比较
- 转换为
matrix
以创建dim
属性 - 应用
max.col
获取每行最大值的列索引 - 然后,
cbind
与行索引 - 从5 根据row/column索引得到对应的'scaleFactor'值
- 使用
[]
将输出分配回 C,以便保留矩阵属性
length
联系起来
C[] <- scaleFactor[cbind(1:3, max.col(matrix(rep(seq_len(ncol(C)) - 1,
each = length(times)) <= c(t(times)), ncol = ncol(times),
byrow = TRUE), "first"))]
-输出
C
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1.1 1.2 1.2 1.4 1.4
[2,] 1 1.3 1.3 1.4 1.4 1.4
[3,] 1 1.2 1.6 1.6 1.6 2.1
我们可以使用 rep
和 asplit
的技巧(将数组拆分为向量列表,在这里很方便)。
C <- t(
mapply(rep, asplit(scaleFactor,1),
times = asplit(cbind(1, t(apply(times, 1, diff))), 1))
)
dim(C)
# [1] 3 100
C[,1:8]
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
# [1,] 1 1.1 1.2 1.2 1.4 1.4 1.4 1.4
# [2,] 1 1.3 1.3 1.4 1.4 1.4 1.6 1.6
# [3,] 1 1.2 1.6 1.6 1.6 2.1 2.1 2.1
它的稳定性取决于times
的最后一列是否相等(这样所有的人迭代相同的时间段数)。
首先将 times
(发生变化的时间段)转换为“持续时间”(每列中的天数),
cbind(1, t(apply(times, 1, diff)))
# [,1] [,2] [,3] [,4]
# [1,] 1 1 2 96
# [2,] 1 2 3 94
# [3,] 1 1 3 95
从那里,我们使用这些数字作为 rep
的 times=
参数。为了保持维度正确,我们为每个人独立地做这件事,这就是为什么我们需要使用 asplit(., 1)
:
asplit(scaleFactor, 1)
# [[1]]
# [1] 1.0 1.1 1.2 1.4
# [[2]]
# [1] 1.0 1.3 1.4 1.6
# [[3]]
# [1] 1.0 1.2 1.6 2.1
然后我们将比例因子与相应的时间配对成rep
:
head(
rep(c(1, 1.1, 1.2, 1.4), times = c(1, 1, 2, 96)),
8)
# [1] 1.0 1.1 1.2 1.2 1.4 1.4 1.4 1.4
为了同时有效地遍历两个矩阵的所有行,我们 asplit
矩阵并将它们输入 mapply
,它传递了 [=24= 的第一行] 与我们的“持续时间”的第一行(times
不同),第二行与第二行等