R语言 匹配行和列名称中包含的数字的矩阵中的按行计算

vs91vp4v  于 2023-02-26  发布在  其他
关注(0)|答案(3)|浏览(164)

bounty将在4天后过期。此问题的答案可获得+50声誉奖励。Adrian正在寻找此问题的最新答案

我有一个矩阵,其中包含几个国家的工业经济信息。我想根据矩阵中元素的位置和相应的列/行名称进行一系列计算。
行/列名称具有三个字母的国家/地区代码,后跟行业编号。行和列名称相同。
计算如下:
1.对于行中的每个元素,都将存在匹配的国家/地区和行业
1.保持产业组合不变,在比赛中把纯粹同一个国家的产业与另一个国家的同一个产业相乘。
我将给予一个简单的例子,尽管我的数据比这个例子大得多。
假设有矩阵a

set.seed(10)

a <- matrix(sample(36) , nrow = 6)
colnames(a) <- rownames(a) <- paste( rep(c("aaa" , "bbb" , "ccc") , each = 2), rep(c(1:2) , times = 3))

给予:

aaa 1 aaa 2 bbb 1 bbb 2 ccc 1 ccc 2
aaa 1     9    19    26     6     5    21
aaa 2    10    24     2    30    36    27
bbb 1    12    15    13    11    20    16
bbb 2     8    28    33    18    34    17
ccc 1    22    35    14    23    29     4
ccc 2     7    31    25    32     1     3

在这个例子中有三个国家“aaa”,“bbb”和“ccc”而只有两个产业,1和2。我想计算在他们自己的国家生产的产业的价值,并相互相乘。
例如,在a[1, 4]中,这将匹配“aaa 1”与“bbb 2”。我想为每个国家乘以行业组合1 - 2,即“aaa 1”-“aaa 2”与“bbb 1”-“bbb 2”(19 * 11 = 209)。沿着对角线块的值将被平方(同一国家的两倍)。
最终矩阵如下所示:

aaa 1 aaa 2 bbb 1 bbb 2 ccc 1 ccc 2
aaa 1    81   361   117   209   261    76
aaa 2   100   576   330   432    10    72
bbb 1   117   209   169   121   377    44
bbb 2   330   432  1089   324    33    54
ccc 1   261    76   377    44   841    16
ccc 2    10    72    33    54     1     9

我用下面这段低效的代码手工计算出来的:

b <- kronecker(diag(1, 3), matrix(1, 2, 2))

b <- (a * b)^2
c <- b

c[1,3] <- 9 * 13
c[1,4] <- 19 * 11
c[1,5] <- 9 * 29
c[1,6] <- 19 * 4

c[2,3] <- 10 * 33
c[2,4] <- 24 * 18
c[2,5] <- 10 * 1
c[2,6] <- 24 * 3

.
.
.

c[6,1] <- 1 * 10
c[6,2] <- 3 * 24
c[6,3] <- 1 * 33
c[6,4] <- 3 * 18

是否有一个灵活的代码来计算这一点,而不考虑数据中的国家和行业数量?我感谢任何帮助。

编辑:我正在处理的矩阵很大(维数超过2000 * 2000)。我需要一个代码来处理这类数据而不冻结R。不幸的是,outer可以解决这里提出的较小矩阵的问题,但在处理较大矩阵时会卡住。

nkhmeac6

nkhmeac61#

更新!

假设每个国家的产业数量相等,dimnames(a)的排序为A1,A2...Am,B1,B2,... Bm,该方法利用了向量化计算的优势,避免了用dimname索引矩阵,从而大大提高了效率并节省了内存。

  • m:行业数量
m <- 2
n <- nrow(a)
block <- matrix(a[kronecker(diag(n/m), matrix(1, m, m)) == 1], m)
block[rep(1:m, len = n), ] * c(block[, c(t(matrix(1:n, m)))])

#      [,1] [,2] [,3] [,4] [,5] [,6]
# [1,]   81  361  117  209  261   76
# [2,]  100  576  330  432   10   72
# [3,]  117  209  169  121  377   44
# [4,]  330  432 1089  324   33   54
# [5,]  261   76  377   44  841   16
# [6,]   10   72   33   54    1    9
旧版本
comb <- function(x, y, mat) {
  prod(mat[outer(c(x[1], y[1]), c(x[2], y[2]), paste)])
}

nms <- strsplit(row.names(a), ' ')
outer(nms, nms, Vectorize(comb, c('x', 'y')), mat = a)
bzzcjhmw

bzzcjhmw2#

如果实际的矩阵an-x-n,且n小于10000,那么类似这样的方法应该可以很好地执行。您可以进一步优化,特别是如果您知道dimnames(a)是排序的(例如,参见@DarrenTsai的answer),但这显然不是必要的。

n <- nrow(a)
nms <- rownames(a)

u <- unlist(strsplit(nms, " "))
country <- u[c(TRUE, FALSE)]
industry <- u[c(FALSE, TRUE)]

i1 <- seq_len(n)
j2 <- rep(i1, each = n)
j1 <- match(paste(country, industry[j2]), nms)
i2 <- match(paste(country[j2], industry), nms)

matrix(a[cbind(i1, j1)] * a[cbind(i2, j2)], n, n)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,]   81  361  117  209  261   76
[2,]  100  576  330  432   10   72
[3,]  117  209  169  121  377   44
[4,]  330  432 1089  324   33   54
[5,]  261   76  377   44  841   16
[6,]   10   72   33   54    1    9

当然,如果dimnames(a)没有排序,但您希望从排序中获益,那么您可以置换a的行和列,对得到的分块矩阵进行操作,并对答案的行和列进行逆置换。

n <- nrow(a)
nms <- rownames(a)

## Number of industries, countries:
ni <- sum(startsWith(nms, substr(nms[1L], 1L, 3L)))
nc <- n %/% ni

p <- order(nms)
a.pp <- a[p, p] # permute

## Essentially @DarrenTsai's answer {uglier but also working for n = 0}:
b <- matrix(a.pp[as.logical(kronecker(diag(nc), matrix(1, ni, ni)))], ni, n)
r.pp <- b[rep.int(seq_len(ni), nc), ] * as.vector(b[, sequence(rep.int(nc, ni), seq_len(ni), ni)])

q <- p
q[q] <- seq_along(q)
r <- r.pp[q, q] # inverse permute

实际上,这里有一些简洁的矩阵代数,r.pp的块[i,j][i,i]a.pp的块[j,j]的元素积,因此r.pp可以看作是b的一种块叉积,因为ba.pp的对角块的水平连接。

oxalkeyp

oxalkeyp3#

您可以尝试下面的代码

> p <- expand.grid(rep(list(row.names(a)), 2))

> p1 <- as.matrix(transform(p, Var2 = paste(sub("\\d+", "", Var1), sub("\\D+", "", Var2), sep = "")))

> p2 <- as.matrix(transform(p, Var1 = paste(sub("\\d+", "", Var2), sub("\\D+", "", Var1), sep = "")))

> `dim<-`(a[p1] * a[p2], dim(a))
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]   81  361  117  209  261   76
[2,]  100  576  330  432   10   72
[3,]  117  209  169  121  377   44
[4,]  330  432 1089  324   33   54
[5,]  261   76  377   44  841   16
[6,]   10   72   33   54    1    9

相关问题