首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从向量存储多个变量的dplyr

从向量存储多个变量的dplyr
EN

Stack Overflow用户
提问于 2018-10-05 12:46:43
回答 2查看 170关注 0票数 1

我在4x4方差协方差矩阵的后验分布上进行本征分解。为此,我在dplyr/tidyverse管道中使用eigen函数:

代码语言:javascript
复制
set.seed(1)
# Variance and covariances of 4 variables
A1  <- rnorm(1000,10,1)
A2  <- rnorm(1000,10,1)
A3  <- rnorm(1000,10,1)
A4  <- rnorm(1000,10,1)
C12 <- rnorm(1000,0,1)
C13 <- rnorm(1000,0,1)
C14 <- rnorm(1000,0,1)
C23 <- rnorm(1000,0,1)
C24 <- rnorm(1000,0,1)
C34 <- rnorm(1000,0,1)

# Create posterior tibble
w1_post <- as_tibble(cbind(A1, C12, C13, C14, A2, C23, C24, A3, C34, A4))

# Get 1st-4th eigenvalues of each variance-covariance matrix
w1_post %>%
  rowwise %>%
    mutate(
      eig1 = 
        eigen(matrix(c(A1, C12, C13, C14, C12, A2, C23, C24, C13, C23,
          A3, C34, C14, C24, C34, A4), nrow = 4))[[1]][1],
      eig2 = 
        eigen(matrix(c(A1, C12, C13, C14, C12, A2, C23, C24, C13, C23,
          A3, C34, C14, C24, C34, A4), nrow = 4))[[1]][2],
      eig3 = 
        eigen(matrix(c(A1, C12, C13, C14, C12, A2, C23, C24, C13, C23,
          A3, C34, C14, C24, C34, A4), nrow = 4))[[1]][3],
      eig4 = 
        eigen(matrix(c(A1, C12, C13, C14, C12, A2, C23, C24, C13, C23,
          A3, C34, C14, C24, C34, A4), nrow = 4))[[1]][4]) %>%
  select(starts_with('eig')) -> eig_post

代码语言:javascript
复制
> eig_post
Source: local data frame [1,000 x 4]
Groups: <by row>

# A tibble: 1,000 x 4
    eig1  eig2  eig3  eig4
   <dbl> <dbl> <dbl> <dbl>
 1  12.3 11.0  10.4   6.67
 2  12.8 10.1   9.19  7.61
 3  13.5 12.2   8.20  7.34
 4  12.7 12.2   8.91  7.68
 5  12.9  9.70  9.41  6.74
 6  12.2 10.6   8.62  7.70
 7  13.1 12.5   9.21  8.34
 8  12.9  9.76  7.87  6.96
 9  12.8 11.6   8.21  6.46
10  12.5 11.6   9.85  8.13
# ... with 990 more rows

正如您所看到的,这是每行执行四次本征分解--这比实际需要的要多4倍,并且减缓了我的脚本!--我可以得到一个dplyr/tidyverse管道,同时对多个变量进行变异,将生成的向量扩展到四个变量中?,所以我需要得到上面的代码生成的内容,但每一行只进行一次特征分解。我以为这样的东西会起作用,但没有运气:

代码语言:javascript
复制
w1_post %>%
  rowwise %>%
    mutate(c(eig1, eig2, eig3, eig4) = 
      eigen(matrix(c(A1, C12, C13, C14, C12, A2, C23, C24, C13, C23,
        A3, C34, C14, C24, C34, A4), nrow = 4))[[1]][1:4]) %>%
  select(starts_with('eig')) -> eig_post
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-05 13:42:58

您可以避免计算特征分解4次,方法是先将计算存储为列表列,然后在随后的步骤中提取值。如果您希望将其保存在管道中,可以这样做:

代码语言:javascript
复制
eig_post <- w1_post %>%
  rowwise %>%
  mutate(
    pre_eig = list(eigen(matrix(c(A1, C12, C13, C14, C12, A2, C23, C24, C13, C23,
                     A3, C34, C14, C24, C34, A4), nrow = 4)))
  ) %>%
  mutate( 
    eig1 = pre_eig[[1]][1], 
    eig2 = pre_eig[[1]][2], 
    eig3 = pre_eig[[1]][3], 
    eig4 = pre_eig[[1]][4]) %>%
  select(starts_with("eig"))
票数 1
EN

Stack Overflow用户

发布于 2018-10-05 13:50:56

下面是一个利用purrr::map系列函数的解决方案:

代码语言:javascript
复制
eig_post <- w1_post %>%

    ## Collapse columns into a vector
    transmute( x = pmap( list(A1, C12, C13, C14, C12, A2, C23, C24, C13, C23,
                              A3, C34, C14, C24, C34, A4), c ) ) %>%

    ## Compose the 4x4 matrices from each vector
    mutate( mtx = map( x, matrix, nrow=4 ) ) %>%

    ## Perform a single decomposition and retrieve all 4 eigenvalues
    mutate( eig = map( mtx, ~eigen(.x)$values ) ) %>%

    ## Annotate the vector of eigenvalues with the desired names
    mutate( eig = map( eig, set_names, str_c("eig", 1:4) ) ) %>%

    ## Reshape the data frame by effectively unnesting the vector
    with( invoke( bind_rows, eig ) )
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52665994

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档