将函数应用于矩阵或数据框的每一行

发布于 2024-10-03 05:24:46 字数 473 浏览 10 评论 0原文

假设我有一个 2 矩阵和一个将 2 向量作为其参数之一的函数。我想将该函数应用于矩阵的每一行并获得一个 n 向量。如何在 R 中做到这一点?

例如,我想计算三个点上的二维标准正态分布的密度:

bivariate.density(x = c(0, 0), mu = c(0, 0), sigma = c(1, 1), rho = 0){
    exp(-1/(2*(1-rho^2))*(x[1]^2/sigma[1]^2+x[2]^2/sigma[2]^2-2*rho*x[1]*x[2]/(sigma[1]*sigma[2]))) * 1/(2*pi*sigma[1]*sigma[2]*sqrt(1-rho^2))
}

out <- rbind(c(1, 2), c(3, 4), c(5, 6))

如何将函数应用于 out 的每一行?

如何以您指定的方式将除点之外的其他参数的值传递给函数?

Suppose I have a n by 2 matrix and a function that takes a 2-vector as one of its arguments. I would like to apply the function to each row of the matrix and get a n-vector. How to do this in R?

For example, I would like to compute the density of a 2D standard Normal distribution on three points:

bivariate.density(x = c(0, 0), mu = c(0, 0), sigma = c(1, 1), rho = 0){
    exp(-1/(2*(1-rho^2))*(x[1]^2/sigma[1]^2+x[2]^2/sigma[2]^2-2*rho*x[1]*x[2]/(sigma[1]*sigma[2]))) * 1/(2*pi*sigma[1]*sigma[2]*sqrt(1-rho^2))
}

out <- rbind(c(1, 2), c(3, 4), c(5, 6))

How to apply the function to each row of out?

How to pass values for the other arguments besides the points to the function in the way you specify?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

我的痛♀有谁懂 2024-10-10 05:24:46

您只需使用 apply() 函数:

R> M <- matrix(1:6, nrow=3, byrow=TRUE)
R> M
     [,1] [,2]
[1,]    1    2
[2,]    3    4
[3,]    5    6
R> apply(M, 1, function(x) 2*x[1]+x[2])
[1]  4 10 16
R> 

这需要一个矩阵并对每一行应用一个(愚蠢的)函数。您将额外的参数传递给函数,作为 apply() 的第四个、第五个……参数。

You simply use the apply() function:

R> M <- matrix(1:6, nrow=3, byrow=TRUE)
R> M
     [,1] [,2]
[1,]    1    2
[2,]    3    4
[3,]    5    6
R> apply(M, 1, function(x) 2*x[1]+x[2])
[1]  4 10 16
R> 

This takes a matrix and applies a (silly) function to each row. You pass extra arguments to the function as fourth, fifth, ... arguments to apply().

合约呢 2024-10-10 05:24:46

如果您想应用 sum 或 Mean 等常见函数,则应使用 rowSums 或 rowMeans ,因为它们比 apply(data, 1, sum ) 方法。否则,请坚持使用 apply(data, 1, fun)。您可以在 FUN 参数之后传递其他参数(正如 Dirk 已经建议的那样):

set.seed(1)
m <- matrix(round(runif(20, 1, 5)), ncol=4)
diag(m) <- NA
m
     [,1] [,2] [,3] [,4]
[1,]   NA    5    2    3
[2,]    2   NA    2    4
[3,]    3    4   NA    5
[4,]    5    4    3   NA
[5,]    2    1    4    4

然后您可以执行以下操作:

apply(m, 1, quantile, probs=c(.25,.5, .75), na.rm=TRUE)
    [,1] [,2] [,3] [,4] [,5]
25%  2.5    2  3.5  3.5 1.75
50%  3.0    2  4.0  4.0 3.00
75%  4.0    3  4.5  4.5 4.00

In case you want to apply common functions such as sum or mean, you should use rowSums or rowMeans since they're faster than apply(data, 1, sum) approach. Otherwise, stick with apply(data, 1, fun). You can pass additional arguments after FUN argument (as Dirk already suggested):

set.seed(1)
m <- matrix(round(runif(20, 1, 5)), ncol=4)
diag(m) <- NA
m
     [,1] [,2] [,3] [,4]
[1,]   NA    5    2    3
[2,]    2   NA    2    4
[3,]    3    4   NA    5
[4,]    5    4    3   NA
[5,]    2    1    4    4

Then you can do something like this:

apply(m, 1, quantile, probs=c(.25,.5, .75), na.rm=TRUE)
    [,1] [,2] [,3] [,4] [,5]
25%  2.5    2  3.5  3.5 1.75
50%  3.0    2  4.0  4.0 3.00
75%  4.0    3  4.5  4.5 4.00
执笔绘流年 2024-10-10 05:24:46

这是将函数应用于矩阵每一行的简短示例。
(这里,应用的函数将每一行标准化为 1。)

注意: apply() 的结果必须使用 转置 >t() 获得与输入矩阵 A 相同的布局。

A <- matrix(c(
  0, 1, 1, 2,
  0, 0, 1, 3,
  0, 0, 1, 3
), nrow = 3, byrow = TRUE)

t(apply(A, 1, function(x) x / sum(x) ))

结果:

     [,1] [,2] [,3] [,4]
[1,]    0 0.25 0.25 0.50
[2,]    0 0.00 0.25 0.75
[3,]    0 0.00 0.25 0.75

Here is a short example of applying a function to each row of a matrix.
(Here, the function applied normalizes every row to 1.)

Note: The result from the apply() had to be transposed using t() to get the same layout as the input matrix A.

A <- matrix(c(
  0, 1, 1, 2,
  0, 0, 1, 3,
  0, 0, 1, 3
), nrow = 3, byrow = TRUE)

t(apply(A, 1, function(x) x / sum(x) ))

Result:

     [,1] [,2] [,3] [,4]
[1,]    0 0.25 0.25 0.50
[2,]    0 0.00 0.25 0.75
[3,]    0 0.00 0.25 0.75
家住魔仙堡 2024-10-10 05:24:46

Apply 的工作做得很好,但速度相当慢。
使用 sapply 和 vapply 可能很有用。 dplyr 的 rowwise 也很有用
让我们看一个如何对任何数据框进行行乘积的示例。

a = data.frame(t(iris[1:10,1:3]))
vapply(a, prod, 0)
sapply(a, prod)

请注意,在使用 vapply/sapply/apply 之前分配给变量是很好的做法,因为它可以大大减少时间。让我们看看微基准测试结果

a = data.frame(t(iris[1:10,1:3]))
b = iris[1:10,1:3]
microbenchmark::microbenchmark(
    apply(b, 1 , prod),
    vapply(a, prod, 0),
    sapply(a, prod) , 
    apply(iris[1:10,1:3], 1 , prod),
    vapply(data.frame(t(iris[1:10,1:3])), prod, 0),
    sapply(data.frame(t(iris[1:10,1:3])), prod) ,
    b %>%  rowwise() %>%
        summarise(p = prod(Sepal.Length,Sepal.Width,Petal.Length))
)

仔细看看 t() 是如何使用的

Apply does the job well, but is quite slow.
Using sapply and vapply could be useful. dplyr's rowwise could also be useful
Let's see an example of how to do row wise product of any data frame.

a = data.frame(t(iris[1:10,1:3]))
vapply(a, prod, 0)
sapply(a, prod)

Note that assigning to variable before using vapply/sapply/ apply is good practice as it reduces time a lot. Let's see microbenchmark results

a = data.frame(t(iris[1:10,1:3]))
b = iris[1:10,1:3]
microbenchmark::microbenchmark(
    apply(b, 1 , prod),
    vapply(a, prod, 0),
    sapply(a, prod) , 
    apply(iris[1:10,1:3], 1 , prod),
    vapply(data.frame(t(iris[1:10,1:3])), prod, 0),
    sapply(data.frame(t(iris[1:10,1:3])), prod) ,
    b %>%  rowwise() %>%
        summarise(p = prod(Sepal.Length,Sepal.Width,Petal.Length))
)

Have a careful look at how t() is being used

北渚 2024-10-10 05:24:46

第一步是创建函数对象,然后应用它。如果您想要一个具有相同行数的矩阵对象,您可以预定义它并使用 object[] 形式,如图所示(否则返回值将被简化为向量):

bvnormdens <- function(x=c(0,0),mu=c(0,0), sigma=c(1,1), rho=0){
     exp(-1/(2*(1-rho^2))*(x[1]^2/sigma[1]^2+
                           x[2]^2/sigma[2]^2-
                           2*rho*x[1]*x[2]/(sigma[1]*sigma[2]))) * 
     1/(2*pi*sigma[1]*sigma[2]*sqrt(1-rho^2))
     }
 out=rbind(c(1,2),c(3,4),c(5,6));

 bvout<-matrix(NA, ncol=1, nrow=3)
 bvout[] <-apply(out, 1, bvnormdens)
 bvout
             [,1]
[1,] 1.306423e-02
[2,] 5.931153e-07
[3,] 9.033134e-15

如果您想使用默认参数以外的其他参数那么调用应该在函数后面包含命名参数:

bvout[] <-apply(out, 1, FUN=bvnormdens, mu=c(-1,1), rho=0.6)

apply() 也可以用于更高维的数组,并且 MARGIN 参数可以是向量也可以是单个整数。

First step would be making the function object, then applying it. If you want a matrix object that has the same number of rows, you can predefine it and use the object[] form as illustrated (otherwise the returned value will be simplified to a vector):

bvnormdens <- function(x=c(0,0),mu=c(0,0), sigma=c(1,1), rho=0){
     exp(-1/(2*(1-rho^2))*(x[1]^2/sigma[1]^2+
                           x[2]^2/sigma[2]^2-
                           2*rho*x[1]*x[2]/(sigma[1]*sigma[2]))) * 
     1/(2*pi*sigma[1]*sigma[2]*sqrt(1-rho^2))
     }
 out=rbind(c(1,2),c(3,4),c(5,6));

 bvout<-matrix(NA, ncol=1, nrow=3)
 bvout[] <-apply(out, 1, bvnormdens)
 bvout
             [,1]
[1,] 1.306423e-02
[2,] 5.931153e-07
[3,] 9.033134e-15

If you wanted to use other than your default parameters then the call should include named arguments after the function:

bvout[] <-apply(out, 1, FUN=bvnormdens, mu=c(-1,1), rho=0.6)

apply() can also be used on higher dimensional arrays and the MARGIN argument can be a vector as well as a single integer.

屌丝范 2024-10-10 05:24:46

如果您想使用数据集的不同部分而不是单个值,另一种方法是使用 rollapply(data, width, FUN, ...)。使用宽度向量允许您在数据集的不同窗口上应用函数。我用它来构建一个自适应过滤例程,尽管它不是很有效。

Another approach if you want to use a varying portion of the dataset instead of a single value is to use rollapply(data, width, FUN, ...). Using a vector of widths allows you to apply a function on a varying window of the dataset. I've used this to build an adaptive filtering routine, though it isn't very efficient.

你如我软肋 2024-10-10 05:24:46

使用 acrossrowSumsrowMeans 的 dplyr 方法。

M <- matrix(1:9, nrow=3, byrow=TRUE)
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9

M %>% as_tibble() %>%
  rowwise() %>% 
  mutate(sum = rowSums(across(where(is.numeric)))) %>% 
  mutate(mean = rowMeans(across(V1:V3))) %>%
  mutate(Max = max(V1:V3)) %>%
  mutate(Min = min(V1:V3)) %>%
  as.matrix()

     V1 V2 V3 sum mean Max Min
[1,]  1  2  3   6    2   3   1
[2,]  4  5  6  15    5   6   4
[3,]  7  8  9  24    8   9   7

A dplyr Approach using across, rowSums and rowMeans.

M <- matrix(1:9, nrow=3, byrow=TRUE)
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9

M %>% as_tibble() %>%
  rowwise() %>% 
  mutate(sum = rowSums(across(where(is.numeric)))) %>% 
  mutate(mean = rowMeans(across(V1:V3))) %>%
  mutate(Max = max(V1:V3)) %>%
  mutate(Min = min(V1:V3)) %>%
  as.matrix()

     V1 V2 V3 sum mean Max Min
[1,]  1  2  3   6    2   3   1
[2,]  4  5  6  15    5   6   4
[3,]  7  8  9  24    8   9   7
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文