【问题标题】:Elegant way of adding columns on a specific position in a data frame在数据框中的特定位置添加列的优雅方式
【发布时间】:2018-11-27 22:19:48
【问题描述】:

我有一个包含 3 个列的 data.frame:日期、价格、价格。我想在价格之后和价格之前添加来自矩阵的列。

df = tibble('date' = c('01/01/2000', '02/01/2000', '03/01/2000'),
        'rate' = c(7.50, 6.50, 5.54),
        'price' = c(92, 94, 96))

我使用输出矩阵的函数计算了速率滞后:

rate_Lags = matrix(data = c(NA, 7.50, 5.54, NA, NA, 7.50), ncol=2, dimnames=list(c(), c('rate_tMinus1', 'rate_tMinus2'))

我想使用名称索引而不是列顺序在价格之后(和价格之前)插入这些滞后。

tibble 包 (Adding a column between two columns in a data.frame) 中的 add_column 函数不起作用,因为它只接受原子向量(因此,如果我有 10 个滞后,我将不得不调用 add_column 10 次)。我可以在我的rate_Lags 矩阵中使用apply。但是,然后,我从rate_Lags 矩阵中丢失了暗名。

如果我知道特定列名的位置(任何检索列名位置的函数?),使用数字索引(子集)(https://stat.ethz.ch/pipermail/r-help/2011-August/285534.html)就可以工作。

有没有什么简单的方法可以在数据框/tibble 对象的特定位置插入一串列s

【问题讨论】:

    标签: r dataframe apply matrix-indexing tibble


    【解决方案1】:

    您可能忽略了以下内容

    library(dplyr)
    I <- which(names(df) == "rate")
    if (I == ncol(df)) {
        cbind(df, rate_Lags)
    } else {
        cbind(select(df, 1:I), rate_Lags, select(df, (I+1):ncol(df))) 
    }
    
    #     date rate rate_tMinus1 rate_tMinus2 price
    # 1 0.0005 7.50           NA           NA    92
    # 2 0.0010 6.50         7.50           NA    94
    # 3 0.0015 5.54         5.54          7.5    96
    

    【讨论】:

    • 我已经编辑了这个问题。 df 的定义中有一个错误:OP 写了01/01/2000 等,这是给0.0005 等的划分序列,而它显然应该是日期。
    【解决方案2】:

    也许这不是很优雅,但你只调用一次函数,我相信它或多或少是通用的。

    fun <- function(DF, M){
      nms_DF <- colnames(DF)
      nms_M <- colnames(M)
      inx <- which(sapply(nms_DF, function(x) length(grep(x, nms_M)) > 0))
      cbind(DF[seq_len(inx)], M, DF[ seq_along(nms_DF)[-seq_len(inx)] ])
    }
    
    fun(df, rate_Lags)
    #        date rate rate_tMinus1 rate_tMinus2 price
    #1 01/01/2000 7.50           NA           NA    92
    #2 02/01/2000 6.50         7.50           NA    94
    #3 03/01/2000 5.54         5.54          7.5    96
    

    【讨论】:

    • 我认为你可以进一步简化这个逻辑——例如idx &lt;- seq.int(1L,match("rate",names(df)))cbind(df[idx], rate_Lags, df[-(idx)])
    • @thelatemail 是的,你是对的,但就像我不需要知道要匹配的列的名称一样。这就是为什么我想到grep。它更复杂,但 sapply 循环在 colnames 属性上应该不会花费太多时间。
    【解决方案3】:

    我们可以将数据集unclass 转换为list,然后使用append 在特定位置插入“rate_Lags”,将list 重新转换为data.frame

    i1 <- match('rate', names(df))
    data.frame(append(unclass(df), as.data.frame(rate_Lags), after = i1))
    #        date rate rate_tMinus1 rate_tMinus2 price
    #1 01/01/2000 7.50           NA           NA    92
    #2 02/01/2000 6.50         7.50           NA    94
    #3 03/01/2000 5.54         5.54          7.5    96
    

    tidyverse

    library(tidyverse)
    rate_Lags %>%
           as_tibble %>%
           append(unclass(df), ., after = i1) %>% 
           bind_cols
    # A tibble: 3 x 5
    #  date        rate rate_tMinus1 rate_tMinus2 price
    #  <chr>      <dbl>        <dbl>        <dbl> <dbl>
    #1 01/01/2000  7.5         NA            NA      92
    #2 02/01/2000  6.5          7.5          NA      94
    #3 03/01/2000  5.54         5.54          7.5    96
    

    【讨论】:

    • 简单的解决方案,它不需要库。唯一的缺点是我不知道插入列的位置(在本例中为 after = 2 )。这可以通过使用which(names(df) = 'rate') 来解决。
    • @EmilianoA.Carlevaro 或使用match('rate', names(df))
    • dplyr中还有一个add_column()函数
    • @meriops 是的,它在那里,但它会添加到 data.frame 中,并且 OP 有几列要添加,而不是单个列
    • 哎呀,我错过了,对不起。然后一种快速而简单的方法可能是将“日期”提取到 df1 中,将“价格”和“价格”提取到 df2 中,然后将列绑定 df1、要插入的列和 df2...
    猜你喜欢
    • 1970-01-01
    • 2013-04-21
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    • 2018-05-03
    • 1970-01-01
    • 2012-06-12
    • 2013-01-27
    相关资源
    最近更新 更多