valores valor una rango posicion otra obtener matriz indirecto indice funcion fila devolver columna coincidir celda buscar r function dictionary matrix apply

valor - Cómo aplicar la función sobre los índices de cada elemento de la matriz



obtener fila y columna de una celda excel (5)

Me pregunto si hay una función incorporada en R que aplica una función a cada elemento de la matriz (por supuesto, la función debe calcularse en base a los índices de la matriz). El equivalente sería algo como esto:

matrix_apply <- function(m, f) { m2 <- m for (r in seq(nrow(m2))) for (c in seq(ncol(m2))) m2[[r, c]] <- f(r, c) return(m2) }

Si no hay tal función incorporada, ¿cuál es la mejor manera de inicializar una matriz para contener los valores obtenidos al calcular una función arbitraria que tiene índices de matriz como parámetros?


El enfoque más simple es simplemente usar un f() que se puede aplicar directamente a los elementos de la matriz. Por ejemplo, usando la matriz m de la respuesta de @ adamleerich

m <- matrix(c(1,2,3,4,5,6,7,8), nrow = 2)

No hay ninguna razón para usar apply() en el caso del ejemplo as.character() . En cambio, podemos operar los elementos de m como si fuera un vector ( realmente es uno) y reemplazarlos en el lugar :

> m[] <- as.character(m) > m [,1] [,2] [,3] [,4] [1,] "1" "3" "5" "7" [2,] "2" "4" "6" "8"

La primera parte de ese bloque es la clave aquí. m[] fuerza a los elementos de m a ser reemplazados por la salida de as.character() , en lugar de sobrescribir m con un vector de caracteres.

Entonces esa es la solución general para aplicar una función a cada elemento de una matriz.

Si uno realmente necesita usar un f() que funcione en índices de filas y columnas, entonces escribiría un f() usando row() y col() :

> m <- matrix(c(1,2,3,4,5,6,7,8), nrow = 2) > row(m) [,1] [,2] [,3] [,4] [1,] 1 1 1 1 [2,] 2 2 2 2 > col(m) [,1] [,2] [,3] [,4] [1,] 1 2 3 4 [2,] 1 2 3 4 > row(m) * col(m) ## `*`(row(m), col(m)) to see this is just f() [,1] [,2] [,3] [,4] [1,] 1 2 3 4 [2,] 2 4 6 8

o uno que use outer() como otros han mostrado. Si f() no está vectorizado, entonces replantearé mi estrategia lo más posible, ya que existe una forma de escribir una versión verdaderamente vectorizada, y ii) una función que no está vectorizada no va a funcionar. escalar muy bien.


Esto no responde exactamente tu pregunta, pero la encontré al tratar de resolver una pregunta similar, así que te mostraré algo.

Supongamos que tiene una función que desea aplicar a cada elemento de una matriz que solo requiere una parte.

mydouble <- function(x) { return(x+x) }

Y di que tienes una matriz X,

> x=c(1,-2,-3,4) > X=matrix(x,2,2) > X [,1] [,2] [1,] 1 -3 [2,] -2 4

entonces haces esto:

res=mydouble(X)

Luego hará un doble de elemento de cada valor.

Sin embargo, si realiza la lógica en la función siguiente, recibirá una advertencia de que no está parametrizada y no se comportará como esperaba.

myabs <- function(x) { if (x<0) { return (-x) } else { return (x) } } > myabs(X) [,1] [,2] [1,] 1 -3 [2,] -2 4 Warning message: In if (x < 0) { : the condition has length > 1 and only the first element will be used

Pero si usa la función apply () puede usarla.

Por ejemplo:

> apply(X,c(1,2),myabs) [,1] [,2] [1,] 1 3 [2,] 2 4

Así que eso es genial, ¿verdad? Bueno, se descompone si tienes una función con dos o más parms. Digamos por ejemplo que tienes esto:

mymath <- function(x,y) { if(x<0) { return(-x*y) } else { return(x*y) } }

En este caso, usa la función apply (). Sin embargo, perderá la matriz, pero los resultados se calculan correctamente. Pueden ser reformados si así lo deseas.

> mapply(mymath,X,X) [1] 1 -4 -9 16 > mapply(mymath,X,2) [1] 2 4 6 8 > matrix(mapply(mymath,X,2),c(2,2)) [,1] [,2] [1,] 2 6 [2,] 4 8


No nos dijiste qué tipo de función quieres aplicar a cada elemento, pero creo que la única razón por la que funcionan los ejemplos en las otras respuestas es porque las funciones ya están vectorizadas. Si realmente desea aplicar una función a cada elemento, el outer no le dará nada especial que la función no le haya dado. ¡Notarás que las respuestas ni siquiera pasaron una matriz al outer !

¿Qué le parece seguir el comentario y el uso de @ Chase?

Por ejemplo, tengo la matriz

m <- matrix(c(1,2,3,4,5,6,7,8), nrow = 2)

Si quiero convertirlo en una matriz de caracteres, elemento por elemento (solo como ejemplo) podría hacerlo

apply(m, c(1,2), as.character)

Por supuesto, como as.character ya está vectorizado, pero mi función especial my.special.function no lo es. Solo toma un argumento, un elemento. No hay una forma directa de conseguir que el outer trabaje con él. Pero, esto funciona

apply(m, c(1,2), my.special.function)


Sospecho que quieres outer :

> mat <- matrix(NA, nrow=5, ncol=3) > outer(1:nrow(mat), 1:ncol(mat) , FUN="*") [,1] [,2] [,3] [1,] 1 2 3 [2,] 2 4 6 [3,] 3 6 9 [4,] 4 8 12 [5,] 5 10 15 > outer(1:nrow(mat), 1:ncol(mat) , FUN=function(r,c) log(r+c) ) [,1] [,2] [,3] [1,] 0.6931472 1.098612 1.386294 [2,] 1.0986123 1.386294 1.609438 [3,] 1.3862944 1.609438 1.791759 [4,] 1.6094379 1.791759 1.945910 [5,] 1.7917595 1.945910 2.079442

Eso produce una buena salida compacta. pero es posible que mapply sea ​​útil en otras situaciones. Es útil pensar mapply como otra forma de hacer la misma operación para la que otros en esta página usan Vectorize . mapply es más general debido a la incapacidad Vectorize para usar funciones "primitivas".

data.frame(mrow=c(row(mat)), # straightens out the arguments mcol=c(col(mat)), m.f.res= mapply(function(r,c) log(r+c), row(mat), col(mat) ) ) # mrow mcol m.f.res 1 1 1 0.6931472 2 2 1 1.0986123 3 3 1 1.3862944 4 4 1 1.6094379 5 5 1 1.7917595 6 1 2 1.0986123 7 2 2 1.3862944 8 3 2 1.6094379 9 4 2 1.7917595 10 5 2 1.9459101 11 1 3 1.3862944 12 2 3 1.6094379 13 3 3 1.7917595 14 4 3 1.9459101 15 5 3 2.0794415

Probablemente no tenías la intención de proporcionar a la función lo que las funciones row () y col () habrían devuelto: Esto produce una matriz de 15 matrices (algo redundantes) 3 x 5:

> outer(row(mat), col(mat) , FUN=function(r,c) log(r+c) )


Usted puede estar pensando en outer :

rows <- 1:10 cols <- 1:10 outer(rows,cols,"+") [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [1,] 2 3 4 5 6 7 8 9 10 11 [2,] 3 4 5 6 7 8 9 10 11 12 [3,] 4 5 6 7 8 9 10 11 12 13 [4,] 5 6 7 8 9 10 11 12 13 14 [5,] 6 7 8 9 10 11 12 13 14 15 [6,] 7 8 9 10 11 12 13 14 15 16 [7,] 8 9 10 11 12 13 14 15 16 17 [8,] 9 10 11 12 13 14 15 16 17 18 [9,] 10 11 12 13 14 15 16 17 18 19 [10,] 11 12 13 14 15 16 17 18 19 20

Claramente, se trata de una función de ejemplo bastante trivial, pero también puede proporcionar su propia función personalizada. Ver ?outer .

Editar

Contrario al comentario a continuación, también puedes usar funciones outer con funciones no vectorizadas ... vectorizándolas.

m <- matrix(1:16,4,4) #A non-vectorized function myFun <- function(x,y,M){ M[x,y] + (x*y) } #Oh noes! outer(1:4,1:4,myFun,m) Error in dim(robj) <- c(dX, dY) : dims [product 16] do not match the length of object [256] #Oh ho! Vectorize()! myVecFun <- Vectorize(myFun,vectorize.args = c(''x'',''y'')) #Voila! outer(1:4,1:4,myVecFun,m) [,1] [,2] [,3] [,4] [1,] 2 7 12 17 [2,] 4 10 16 22 [3,] 6 13 20 27 [4,] 8 16 24 32