dplyr用于存储向量中的可变变量

dplyr用于存储向量中的可变变量,r,dplyr,R,Dplyr,我正在对4x4方差协方差矩阵的后验分布执行特征分解。为此,我在dplyr/tidyverse管道中使用本征函数: 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 &

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

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

通过先将计算存储为列表列,然后在后续步骤中提取值,可以避免计算特征分解4次。如果您想将其保留在管道中,可以这样做:

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"))

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

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 ) )

谢谢-就像一个魅力;作为旁注,我将其更改为在相同的突变中执行所有的突变:mutatepre_eig=listeInMatrix XCA1、C12、C12、A2、C23、C24、C13、C23、A3、C34、C14、C24、C34、A4、nrow=4、eig1=pre_eig[[1]]1、eig2=pre_eig[[1]]2、eig3=pre_eig[[1]]3、eig4=pre_eig[[1]]4]当然,这也是可能的,但为了清楚起见,我在回答中把它分成了两半。一个快速的微基准测试表明,顺便说一句,这种方法比你最初的方法至少快3倍。后续的研究表明,这种方法似乎比我的方法略快,仍然快25%左右
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"))
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 ) )