【问题标题】:R - detect and summarize changes in matricesR - 检测和总结矩阵的变化
【发布时间】:2025-12-19 04:10:07
【问题描述】:

我有两组矩阵。每个矩阵的维度为 100x100,我有 240 个(假设每个矩阵是在一个月内收集的,我有一个由 240 个月的 100x100 矩阵组成的数据集)。

矩阵中的值范围从 1 到 15,代表植被类型(草、热带森林、苔原等)。

我的第一组矩阵m1 是我的对照实验。我的第二组矩阵m2 是一个气候变化实验,其中气候变化会引起矩阵值的变化。

因此,数据表示如下:

m1:240 个 100x100 矩阵的集合,每个矩阵对应一个月(因此有 240 个月的数据)。这是我的控制数据

m2:与m1相同,但由于气候的一些变化,数值有所不同。这是我的实验数据。

这是一些数据:

# generate dataset 1
set.seed(4)
someData1 <- round(runif(100 * 100 * 240, min=1, max=15),digits=0)

# generate dataset2
set.seed(5)
someData2 <- round(runif(100 * 100 * 240, min=1, max=15),digits=0)

# create matrices
k = 240; n=100; m = 100
m1 <- array(someData1, c(n,m,k))
m2 <- array(someData2, c(n,m,k))

我想做的是以这种方式比较m2 相对于m1 的每个单元格:

  • 值不同吗?是/否
  • 如果是,有什么变化?例如 1 到 10,或 2 到 7 等等。

相对于m1 中的所有 240 个矩阵,对m2 中的所有 240 个矩阵执行相同操作。

到最后,我希望能够:

  • 有一个二进制矩阵来显示值是否发生了变化;
  • 有一个表格,其中包含每个类别的变化频率(即 1 到 10、2 到 7 等)。

从概念上讲,我需要实现的是这样的:

为简单起见,我绘制了 5x5 矩阵而不是 100x100 矩阵。

如何在 R 中实现这一点?

【问题讨论】:

  • @NealFultz 不,我感兴趣的不是差异的大小。相反,我想知道植被是否从热带森林 (1) 变为大草原 (5)。请注意,在这种情况下,知道差异并不意味着什么。

标签: r matrix detection


【解决方案1】:

要比较两个矩阵,请使用==!=

what.changed <- m1 != m2 # T if changed F if not
changes <- ifelse(what.changed, paste(m1, 'to', m2), NA)
changes # for your little matrices not the 100x100
     [,1]     [,2]      [,3]    
[1,] NA       "7 to 10" "6 to 7"
[2,] NA       NA        NA      
[3,] "3 to 4" "6 to 8"  NA      

您的矩阵看起来相当大,所以我不确定某种稀疏矩阵方法是否会更好。关于将更改存储为字符串(“3 到 4”),也许您只能将更改存储在实际发生更改的位置,而不是创建一个大多数元素为 NA 的大矩阵。例如

或者您可以创建一个 CSV/数据框来总结您的更改,例如(使用您的 100x100x240 矩阵来演示 3 个坐标):

# find coordinates of changes
change.coords <- which(m1 != m2, arr.ind=T)
colnames(change.coords) <- c('x', 'y', 'time') # whatever makes sense to your application
changes <- data.frame(change.coords, old=m1[change.coords], new=m2[change.coords])
head(changes)
  x y time old new
1 1 1    1   9   4
2 2 1    1   1  11
3 3 1    1   5  14
4 5 1    1  12   2
5 6 1    1   5  11
6 7 1    1  11   8

然后您可以根据需要将其打印出来,而无需存储大量字符串(“X 到 Y”)和 NA,例如(不要对您的大型示例矩阵执行此操作,有太多的变化,它将打印它们 /all/):

with(changes, message(sprintf("Coords (%i, %i, %i): %i to %i\n", 
       x, y, time, old, new)))

【讨论】:

  • 实际上,您的方法效果很好。创建矩阵changes 花费了大约 5 秒。现在的挑战是,如何汇总每个字符串的统计信息?例如相对于元素总数有多少“3到4”变化?
  • 试试table(changes)prop.table(table(changes))。见?table?prop.table