基于索引列创建新列

时间:2017-10-23 08:26:34

标签: r dataframe dplyr tidyverse

我有一个包含n个观察点的数据集和一个包含观察指数的列,例如

col1 col2 col3 ID
12    0    4    1
6     5    3    1
5     21   42   2

并希望根据我的索引创建一个新列,如

col1 col2 col3 ID col_new
12    0    4    1   12
6     5    3    1   6
5     21   42   2   21

没有for循环。其实我正在做

col_new <- rep(NA, length(ID))
for (i in 1:length(ID))
{
   col_new[i] <- df[i, ID[i]]
}

是否有更好的或(tidyverse)方式?

4 个答案:

答案 0 :(得分:5)

对于可能的tidyverse方法,如何将dplyr::mutatepurrr::map2_int结合使用。

library(dplyr)
library(purrr)

mutate(df, new_col = map2_int(row_number(), ID, ~ df[.x, .y]))
#>   col1 col2 col3 ID new_col
#> 1   12    0    4  1      12
#> 2    6    5    3  1       6
#> 3    5   21   42  2      21

数据

df <- read.table(text = "col1 col2 col3 ID
12    0    4    1
6     5    3    1
5     21   42   2", header = TRUE)

答案 1 :(得分:3)

我们可以使用来自row/column的{​​{1}}索引,这应该非常快

base R

答案 2 :(得分:2)

使用data.table的解决方案:

library(data.table)
# Using OPs data
setDT(df)
df[, col_new := get(paste0("col", ID)), 1:nrow(df)]

# df
   col1 col2 col3 ID col_new
1:   12    0    4  1      12
2:    6    5    3  1       6
3:    5   21   42  2      21

说明:

  • 每行:1:nrow(df)
  • 使用ID获取相应的列:get(paste0("col", ID))
  • 将此值写入新列:col_new :=

答案 3 :(得分:1)

另一种整齐的方法,这次只使用tidyrdplyr

df %>%
    gather(column, col_new, -ID)  %>%  
    filter(paste0('col', ID) == column) %>%
    select(col_new) %>%
    cbind(df, .)

它比@ markdly优雅的单行更长,但是如果你像我一样并且大部分时间都被purrr弄糊涂了,这可能会更容易阅读。