【问题标题】:How to append a matrix of columns to a data frame in dplyr?如何将列矩阵附加到 dplyr 中的数据框?
【发布时间】:2018-08-20 18:59:00
【问题描述】:

我想将 (mutate) 多列附加到数据框中,这些列存储在矩阵中。有没有办法使用 tidyverse 中的函数来做到这一点? (请注意,虽然可以使用 base:: 函数。)同样,我要问的是使用 tidyverse 中的函数最自然(或惯用)的方法是什么。

例如,假设我们估计一个分位数回归:

library(dplyr)

tibble(x = runif(100)) %>%
  mutate(y = rnorm(n())) ->
  EstimationData

library(quantreg)

taus <- (1:9)/10
rq_fit <- rq(y ~ x, tau = taus, data = EstimationData)

我们想根据x 的以下值来预测模型:

PredictionData <- tibble(x = seq(0, 1, len = 10))

这可以通过以下方式完成:

predict(rq_fit, newdata = PredictionData)

返回一个矩阵(每个tau对应一列)。很自然的事情是将预测与其对应的xs 打包在一起。人们可能希望能够将上述矩阵mutate() 转换为PredictionData,但据我所知,这是不可能的。一种可能性是:

PredictionData %>%
  data.frame(predict(rq_fit, newdata = .), check.names = FALSE) # (*)

虽然它依赖于base::data.frame(),但效果很好(特别是因为矩阵列有名称)。请注意,tibble()as_tibble() 不起作用。

尝试编写更惯用的 tidyverse 代码的一种方法是将矩阵转换为向量列表,如下所示:

row_split <- function(X) split(X, row(X, as.factor = TRUE))

PredictionData %>%
  mutate(y = row_split(predict(rq_fit, newdata = .))) %>%
  unnest(.id = 'tau_ix') %>%
  mutate(tau = taus[as.integer(tau_ix)]) %>%
  select(-tau_ix)

但我不相信它会更好。

方法(*)是最好的方法吗?

【问题讨论】:

    标签: r matrix dplyr


    【解决方案1】:

    我想你想要的功能是dplyr::bind_cols()。请注意,这不适用于矩阵,因此您还必须使用 dplyr::as_tibble()

    如果您的目标是将事物保持为 tibble,请使用 dplyr 等的函数,我认为这是最简单的方法:

    PredictionData %>% bind_cols(as_tibble(predict(rq_fit, newdata = .)))
    

    但是,对于dplyr 方法,有人可能会认为这有点过于“从内到外”而不是“从左到右”而不是真正地道。所以,也许你想要更多类似的东西

    rq_fit %>%
        predict(newdata = PredictionData) %>%
        as_tibble() %>%
        bind_cols(PredictionData) %>%
        select(x, everything())
    

    两种方法都给出以下输出:

    # A tibble: 10 x 10
               x `tau= 0.1` `tau= 0.2` `tau= 0.3` `tau= 0.4`   `tau= 0.5` `tau= 0.6` `tau= 0.7` `tau= 0.8` `tau= 0.9`
           <dbl>      <dbl>      <dbl>      <dbl>      <dbl>        <dbl>      <dbl>      <dbl>      <dbl>      <dbl>
     1 0.0000000 -1.5755585 -0.8082654 -0.3133431 -0.1952309  0.058074887 0.44450275  0.6679990  0.8802325   1.650510
     2 0.1111111 -1.4767907 -0.7915847 -0.3517192 -0.1909820  0.041473996 0.39935461  0.6132367  0.8618259   1.618999
     3 0.2222222 -1.3780228 -0.7749040 -0.3900952 -0.1867331  0.024873104 0.35420647  0.5584744  0.8434194   1.587488
     4 0.3333333 -1.2792549 -0.7582233 -0.4284712 -0.1824842  0.008272213 0.30905833  0.5037121  0.8250128   1.555976
     5 0.4444444 -1.1804871 -0.7415425 -0.4668472 -0.1782353 -0.008328679 0.26391019  0.4489498  0.8066063   1.524465
     6 0.5555556 -1.0817192 -0.7248618 -0.5052233 -0.1739865 -0.024929570 0.21876205  0.3941875  0.7881997   1.492954
     7 0.6666667 -0.9829513 -0.7081811 -0.5435993 -0.1697376 -0.041530462 0.17361391  0.3394252  0.7697932   1.461442
     8 0.7777778 -0.8841835 -0.6915004 -0.5819753 -0.1654887 -0.058131353 0.12846577  0.2846630  0.7513866   1.429931
     9 0.8888889 -0.7854156 -0.6748196 -0.6203513 -0.1612398 -0.074732245 0.08331763  0.2299007  0.7329801   1.398419
    10 1.0000000 -0.6866477 -0.6581389 -0.6587274 -0.1569909 -0.091333136 0.03816949  0.1751384  0.7145735   1.366908
    

    数据

    为了重现性,我使用您的代码创建了数据,但首先设置了种子:

    set.seed(1234)
    
    library(dplyr)
    
    tibble(x = runif(100)) %>%
        mutate(y = rnorm(n())) ->
        EstimationData
    
    library(quantreg)
    
    taus <- (1:9)/10
    rq_fit <- rq(y ~ x, tau = taus, data = EstimationData)
    
    PredictionData <- tibble(x = seq(0, 1, len = 10))
    

    【讨论】:

    • 我认为你是对的,dplyr::bind_cols()base::data.frame() 更快、更具可读性(并且生活在 tidyverse 中!)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    相关资源
    最近更新 更多