通过根据另一列的值选择列来创建新变量

时间:2021-06-12 00:44:51

标签: r dplyr tidyverse tidyr

假设我们有以下数据框:

df <- data.frame(seq(1, 21, 1),
             seq(-60, 0, 3),
             seq(200, 300, 5),
             sample(1:3))
colnames(df) <- c("Var1", "Var2", "Var3", "Sample") 
<头>
Var1 Var2 Var3 示例
1 -60 200 3
2 -57 205 2
3 -54 110 1
... ... ... ...

我想创建一个新变量,它的值是从与“示例”中的值对应的列中选择的。也就是说,对于上面的例子,结果应该类似于

<头>
Var1 Var2 Var3 示例 Newvar
1 -60 200 3 200
2 -57 205 2 -57
3 -54 110 1 3
... ... ... ... ...

我正在使用 dplyr,因此尝试了以下操作,但我不确定如何解决 paste0 未将“Sample”注册为对象的事实:

df %>%
  mutate(Newvar = !!as.symbol(paste0("Var", Sample)))

任何帮助将不胜感激。

5 个答案:

答案 0 :(得分:4)

您可以使用 c_across()

df %>% 
  rowwise() %>% 
  mutate(newvar = c_across(Var1:Var3)[Sample]) %>% 
  ungroup()

# # A tibble: 21 x 5
#     Var1  Var2  Var3 Sample newvar
#    <dbl> <dbl> <dbl>  <int>  <dbl>
#  1     1   -60   200      2    -60
#  2     2   -57   205      1      2
#  3     3   -54   210      3    210
# ...

答案 1 :(得分:0)

library(tidyverse)

df <- data.frame(seq(1, 21, 1),
                 seq(-60, 0, 3),
                 seq(200, 300, 5),
                 sample(1:3))
colnames(df) <- c("Var1", "Var2", "Var3", "Sample")



df %>%
    mutate(Newbar = df$Sample %>%
               map2_dbl(1:length(.), ~ df[..2, ..1]) )
#>    Var1 Var2 Var3 Sample Newbar
#> 1     1  -60  200      3    200
#> 2     2  -57  205      1      2
#> 3     3  -54  210      2    -54
#> 4     4  -51  215      3    215
#> 5     5  -48  220      1      5
#> 6     6  -45  225      2    -45
#> 7     7  -42  230      3    230
#> 8     8  -39  235      1      8
#> 9     9  -36  240      2    -36
#> 10   10  -33  245      3    245
#> 11   11  -30  250      1     11
#> 12   12  -27  255      2    -27
#> 13   13  -24  260      3    260
#> 14   14  -21  265      1     14
#> 15   15  -18  270      2    -18
#> 16   16  -15  275      3    275
#> 17   17  -12  280      1     17
#> 18   18   -9  285      2     -9
#> 19   19   -6  290      3    290
#> 20   20   -3  295      1     20
#> 21   21    0  300      2      0

reprex package (v2.0.0) 于 2021 年 6 月 11 日创建

答案 2 :(得分:0)

这是一个基本的 R 解决方案。您使用第一个“[.]”将选择限制为前 3 行,然后在第二个“[.]”内使用两列矩阵“链接”选择:

df$Newvar <- df[1:3][cbind(1:nrow(df), df$Sample)]
#-------------
> df
   Var1 Var2 Var3 Sample Newvar
1     1  -60  200      1      1
2     2  -57  205      2    -57
3     3  -54  210      3    210
4     4  -51  215      1      4
5     5  -48  220      2    -48
6     6  -45  225      3    225
7     7  -42  230      1      7
8     8  -39  235      2    -39
9     9  -36  240      3    240
10   10  -33  245      1     10
11   11  -30  250      2    -30
12   12  -27  255      3    255
13   13  -24  260      1     13
14   14  -21  265      2    -21
15   15  -18  270      3    270
16   16  -15  275      1     16
17   17  -12  280      2    -12
18   18   -9  285      3    285
19   19   -6  290      1     19
20   20   -3  295      2     -3
21   21    0  300      3    300

我得到的选择与 akrun 不同,因为没有调用 set.seed 并且您调用 sample 不够“丰富”。也许 dplyr 中有一个不同的 sample 函数具有不同的默认 replace 参数? (不,不是这样。只是用一个向量调用 sample 只会给你一个向量的排列,所以模式重复了 7 次。你会得到一个警告是采样的长度向量不是数据帧中行数的精确倍数。)

答案 3 :(得分:0)

使用 map2_dbl 中的 purrr 和列名作为引用而不是索引

library(dplyr)
library(purrr)
df$newvar <- map2_dbl(seq_len(nrow(df)), paste0("Var", df$Sample),
  function(x, y) { df[x, y]})

df
#>    Var1 Var2 Var3 Sample newvar
#> 1     1  -60  200      1      1
#> 2     2  -57  205      3    205
#> 3     3  -54  210      2    -54
#> 4     4  -51  215      1      4
#> 5     5  -48  220      3    220
#> 6     6  -45  225      2    -45
#> 7     7  -42  230      1      7
#> 8     8  -39  235      3    235
#> 9     9  -36  240      2    -36
#> 10   10  -33  245      1     10
#> 11   11  -30  250      3    250
#> 12   12  -27  255      2    -27
#> 13   13  -24  260      1     13
#> 14   14  -21  265      3    265
#> 15   15  -18  270      2    -18
#> 16   16  -15  275      1     16
#> 17   17  -12  280      3    280
#> 18   18   -9  285      2     -9
#> 19   19   -6  290      1     19
#> 20   20   -3  295      3    295
#> 21   21    0  300      2      0

reprex package (v2.0.0) 于 2021 年 6 月 12 日创建

答案 4 :(得分:0)

您可以将 getrowwise() 一起使用

set.seed(1)
df <- data.frame(Var1 = sample(1:100, 5),
                 Var2 = sample(1:100, 5),
                 Var3 = sample(1:100, 5),
                 sample = sample(1:3, 5, T))

df
#>   Var1 Var2 Var3 sample
#> 1   68   43   97      3
#> 2   39   14   85      1
#> 3    1   82   21      3
#> 4   34   59   54      1
#> 5   87   51   74      1
library(dplyr)

df %>% rowwise() %>%
  mutate(newcol = get(paste0('Var', sample)))

#> # A tibble: 5 x 5
#> # Rowwise: 
#>    Var1  Var2  Var3 sample newcol
#>   <int> <int> <int>  <int>  <int>
#> 1    68    43    97      3     97
#> 2    39    14    85      1     39
#> 3     1    82    21      3     21
#> 4    34    59    54      1     34
#> 5    87    51    74      1     87

reprex package (v2.0.0) 于 2021 年 6 月 12 日创建