Манипуляции со строками в матрицах: проблема размерности

Я пытаюсь определить функцию, управляющую матрицами строк в R.

{+,*} УМНОЖЕНИЕ МАТРИЦ

{+,*}-произведение двух квадратных матриц A и B размерности n представляет собой матрицу C, определяемую элементами: Ci,j = суммаk=1,...,nAi,k * Bk,j.

Например, рассмотрим матрицу M <- matrix(c(a,b,0,0,c,d,0,0,e),3,3). Тогда M умножить на M равно M <- matrix(c(a^2,a*b+b*c,b*d,0,c^2,c*d+d*e,0,0,e^2),3,3).

{c(,),paste0(,)} УМНОЖЕНИЕ МАТРИЦ

Правило этой операции, которое я хотел бы реализовать, такое же, как и в предыдущем заявленном умножении с существенной мутацией, состоящей в том, что сумма должна быть конкатенацией, а произведение должно быть пастой. Другими словами, там, где в предыдущей формуле мы нашли a+b, теперь на выходе должно быть «c(a,b)», а когда мы нашли a*b, теперь мы должны прочитать это как paste0(a,b).

Некоторые из обычных свойств должны соблюдаться, а именно дистрибутивные свойства и свойства нулевого элемента. Следовательно, если a <- c("q",0,"w") и b <- c("e"), то a*b <- c("qe",0,"we") (и мы должны свободно забыть об элементе 0, отбросив его, так как он не повлияет на вычисление.

Более того, мы перемножаем матрицы одинаковой размерности, поэтому каждый элемент Ci,j = Sumk=1,...,n Ai,k * Bk,j теперь следует читать как c("A[i,1]B[1,j]",...,"A[i,n]B[n,j]").

Для простоты будем считать B всегда простой матрицей, что означает, что каждый из ее элементов является атомарной строкой, а не конкатенацией строк (обобщение — это последующий шаг).

Приведем пример. Пусть A <- matrix(c("a","b",0,0,"c","d",0,0,"e"),3,3), затем mult(A,A) = matrix(c("aa",c("ab","bc"),"bd",0,"cc",c("cd","de"),0,0,"ee"),3,3) и mult(mult(A,A),A) = matrix(c("aaa",c("aab","abc","bcc"),c("abd","bcd","bde"),0,"ccc",c("ccd","cde","dee"),0,0,"eee"),3,3).

ЧАСТИЧНАЯ (НЕ РАБОТАЮЩАЯ) РЕАЛИЗАЦИЯ

Рассмотрим в качестве входных данных пару матриц nxn M , N с 0 или массивом строк c(s1 ,s2,...) как элементы i,j. В качестве вывода я хотел бы иметь матрицу MN = M x N, где умножение определяется по аналогии с символическим умножением:

MNi,j = 0, если Mi,. или N.,j равно 0
MNi,j = paste(Mi,.,N.,j) в противном случае (с использованием свойства distributive элемента paste())

Я дал (неверно, неправильно проверяет нули) определение базовой функции вставки строки/столбца как

MijPaste <- function(Row,Col){
  if(Col[1]=="0"){
    Mij <- 0
  } else if(Row[1]=="0"){
      Mij <- 0
    } else
      Mij <- paste(Row,Col,sep="")
  return(Mij)
}

Я не смог перейти от этого шага к правильному определению функции умножения, так как элемент Mij, который я хотел бы вставить в матрицу, имеет неправильную размерность. И, следовательно, я получаю ошибку number of items to replace is not a multiple of replacement length. Моя текущая реализация:

# define the dimension of the matrix, here for example 3
dim <- 3
# define the Multiplication function as an iteration of the MijPaste function
Mult <- function(M1,M2){
    #allocate a matrix of dimension nxn
    M <-  matrix(0,dim,dim)
    #for each element i,j define it as the MijPaste of row i column j
      for(i in 1:dim){
      for(j in 1:dim){
        stringi <- M1[i,]
        stringj <- M2[,j]
        M[i,j] <- MijPaste(stringi,stringj)
      }
    }
  return(M)
}

Код не работает. Я мог бы, вероятно, преобразовать матрицу в многомерный массив, но я хотел бы, чтобы вывод можно было использовать в качестве матрицы для дальнейшего умножения (например, для определения (MxN)xC).

Как я могу сделать?

Спасибо!

P.S. Вы можете протестировать код, используя простую примерную матрицу

Matr <- matrix(c("11","12","13","21","22","23","31","32","33"),dim,dim)

и работает

Mult(Matr,Matr)

person gvdr    schedule 28.03.2013    source источник
comment
Это не работает, потому что у вас не может быть вектора (длиной ›= 2) в слоте матрицы, т. е. вы не можете присвоить c("A[i,1]B[1,j]",...,"A[i,n]B[n,j]") M[i,j]. Вы должны сначала свернуть этот вектор в строку длиной один символ, как я указал в своих комментариях ниже.   -  person Ferdinand.kraft    schedule 30.03.2013
comment
Хорошо, это делает вашу точку зрения. Затем мне, вероятно, придется свернуть ее в строку длиной один, используя какой-нибудь символ-разделитель, и снова разбить ее, прежде чем выполнять умножение. Надеюсь, это осуществимо.   -  person gvdr    schedule 30.03.2013


Ответы (2)


Вы можете использовать paste напрямую с матрицами, если вы зададите размеры вручную:

MN <- matrix(paste(M, N, sep=""), nrow=nrow(M), ncol=ncol(M))

Теперь отфильтруйте нули и замените:

MN[(M==0) | (N==0)] <- 0

РЕДАКТИРОВАТЬ: точечный продукт, показанный выше, НЕ является тем, что хочет ОП.

Как я сказал в комментарии, вы можете исправить свою функцию, добавив collapse="" к своей первой функции. Я получаю следующие результаты:

> M <- matrix(LETTERS[1:9],3,3)
> N <- matrix(LETTERS[10:18],3,3)

> M
     [,1] [,2] [,3]
[1,] "A"  "D"  "G" 
[2,] "B"  "E"  "H" 
[3,] "C"  "F"  "I" 
> N
     [,1] [,2] [,3]
[1,] "J"  "M"  "P" 
[2,] "K"  "N"  "Q" 
[3,] "L"  "O"  "R" 

> Mult(M,N)
     [,1]     [,2]     [,3]    
[1,] "AJDKGL" "AMDNGO" "APDQGR"
[2,] "BJEKHL" "BMENHO" "BPEQHR"
[3,] "CJFKIL" "CMFNIO" "CPFQIR"

Как видите, ваша функция сопоставляет элементы в матрицах M и N перед вставкой.

Если вы хотите сохранить элементы каждой матрицы вместе, вы можете использовать эти две строки:

> coll <- function(x)paste(x,collapse="")
> outer(apply(M,1,coll),apply(N,2,coll),paste0)
     [,1]     [,2]     [,3]    
[1,] "ADGJKL" "ADGMNO" "ADGPQR"
[2,] "BEHJKL" "BEHMNO" "BEHPQR"
[3,] "CFIJKL" "CFIMNO" "CFIPQR"

Конечно, после этого вам придется вставлять нули вручную.

person Ferdinand.kraft    schedule 28.03.2013
comment
Возможно, я ошибаюсь, но я боюсь, что предыдущая функция выдает в качестве вывода поточечное произведение и не может быть принудительно (как встроенная) выдавать построчное произведение, что и является желаемым результатом. - person gvdr; 29.03.2013
comment
В этом случае все, что вам нужно сделать, это добавить collapse="" к вашему вызову paste. то есть, вот так: paste(Row,Col,sep="",collapse="") - person Ferdinand.kraft; 29.03.2013
comment
Кроме того, в вашей функции вы только проверяете, равен ли первый элемент Row и Col нулю, чтобы вернуть ноль. Это кажется странным. Что именно вы хотите? M[i,j] должно быть равно нулю, если любой элемент в Row/Col равен нулю, или только если все из них равны нулю? - person Ferdinand.kraft; 29.03.2013
comment
Да, ты совершенно прав. Чек не правильный. Я думаю, что лучший способ объяснить, что я хочу, — это использовать арифметику (+,), где ab — это вставить (a,b), а +b — это c(a,b) и операция работает с обычными свойствами для 0. Я объясню это для всех в основной задаче, приведя лучший пример. - person gvdr; 30.03.2013
comment
@gvdr, буду ждать! :-) - person Ferdinand.kraft; 30.03.2013
comment
Неа. Смотрите мой комментарий в вопросе. - person Ferdinand.kraft; 30.03.2013

pmat <- function(m1, m2) matrix(
          ifelse(m1=="0"|m2=="0", "0", paste0(m1,m2) ) ,
                            dim(m1)[1], dim(m1)[2] )


> pmat(Matr, Matr)
     [,1]   [,2]   [,3]  
[1,] "1111" "2121" "3131"
[2,] "1212" "2222" "3232"
[3,] "1313" "2323" "3333"

Я не мог сказать, готовы ли вы к умножению измерений или нет. Если вы ожидаете N элементов на индекс, вам нужна функция kronecker, для которой потребуется немного другая функция:

Вставлять:

Может быть, вы должны были опубликовать лучший тестовый пример? Тогда вы могли бы более четко указать, что вы хотели. Это показывает, как kronecker-примененный pmat, перестроенный в виде массива, даст вам MN[1,1] в качестве 1-го столбца первой матрицы:

 M <- matrix(c("a1","b1","c1","0"),2,2)
 N <- matrix(c("c2","d2","e2","f2"),2,2)
 MN <- array( kmat,c( 2,2,4))
 MN[ , 1,1]
#[1] "a1c2" "a1d2"

> pmat <- function(m1, m2) matrix( ifelse(m1=="0"|m2=="0", "0", paste0(m1,m2) )  )
> kronecker(Matr, Matr, pmat)
      [,1]   [,2]   [,3]   [,4]   [,5]   [,6]   [,7]   [,8]   [,9]  
 [1,] "1111" "1121" "1131" "2111" "2121" "2131" "3111" "3121" "3131"
 [2,] "1112" "1122" "1132" "2112" "2122" "2132" "3112" "3122" "3132"
 [3,] "1113" "1123" "1133" "2113" "2123" "2133" "3113" "3123" "3133"
 [4,] "1211" "1221" "1231" "2211" "2221" "2231" "3211" "3221" "3231"
 [5,] "1212" "1222" "1232" "2212" "2222" "2232" "3212" "3222" "3232"
 [6,] "1213" "1223" "1233" "2213" "2223" "2233" "3213" "3223" "3233"
 [7,] "1311" "1321" "1331" "2311" "2321" "2331" "3311" "3321" "3331"
 [8,] "1312" "1322" "1332" "2312" "2322" "2332" "3312" "3322" "3332"
 [9,] "1313" "1323" "1333" "2313" "2323" "2333" "3313" "3323" "3333"
person IRTFM    schedule 28.03.2013
comment
Я не готов к многомерному умножению в окончательном матричном выводе, но у меня нет проблем с многомерным умножением для получения вывода. - person gvdr; 29.03.2013
comment
Проблема здесь в том, что в моей позиции MN [1,1] я хотел бы иметь строку M [1,.] на N [.,1] произведение столбца, а не поточечное произведение. Если, например, первая строка M равна c("a","b"), а первая строка столбца N равна c("c","d"), вывод в MN [1,1 ] должно быть c("ac","bd"). - person gvdr; 29.03.2013
comment
Это очень полезно, но все же не то, что я хотел. Рассмотрим матрицу M <- matrix(c("a","b",0,0,"c","d",0,0,"e"),3,3). Если я правильно использую функцию Кронекера, если я вычисляю M умножить на M, результатом будет matrix(c("aa","bb",0,0,"cc","dd",0,0,"ee"),3,3), в то время как желаемый результат, по аналогии с обычным умножением матриц %*%, должен быть matrix(c("aa",c("ab","bc"),0,0,"cc","cd+de",0,0,"ee"),3,3) (или, используя общую (+,*) арифметику, matrix(c(a^2,ab+bc,0,0,c^2,cd+de,0,0,e^2),3,3)). Прошу прощения за то, что раньше не был более ясным. - person gvdr; 30.03.2013