突变列值而不是列名

时间:2018-09-24 11:24:27

标签: r dplyr

library(tidyverse)

# Attempt 1
tribble(
  ~A, ~Y, ~V1, ~V2, ~V3,
  "One", 2, 89, 52, 37,
  "Two", 3, 45, 34, 86,
  "alpha", 1, 33, 36, 43,
  "beta", 1, 21, 33, 45,

) %>% 
  mutate(selectYCol = paste0("V", Y))

#> # A tibble: 4 x 6
#>   A         Y    V1    V2    V3 selectYCol
#>   <chr> <dbl> <dbl> <dbl> <dbl> <chr>     
#> 1 One       2    89    52    37 V2        
#> 2 Two       3    45    34    86 V3        
#> 3 alpha     1    33    36    43 V1        
#> 4 beta      1    21    33    45 V1

# Attempt 2
tribble(
  ~A, ~Y, ~V1, ~V2, ~V3,
  "One", 2, 89, 52, 37,
  "Two", 3, 45, 34, 86,
  "alpha", 1, 33, 36, 43,
  "beta", 1, 21, 33, 45,

) %>% 
  mutate(selectYCol = glue::glue("V{Y}"))

#> # A tibble: 4 x 6
#>   A         Y    V1    V2    V3 selectYCol
#>   <chr> <dbl> <dbl> <dbl> <dbl> <S3: glue>
#> 1 One       2    89    52    37 V2        
#> 2 Two       3    45    34    86 V3        
#> 3 alpha     1    33    36    43 V1        
#> 4 beta      1    21    33    45 V1

在selectYCol中,我们需要列值而不是列名。 “ V”是静态的,其数字基于Y列。

因此,selectYCol结果应为52、86、33、21,分别来自V2,V3,V1,V1列。

注意:有两个小动作(尝试)试图用不同的方法来做同一件事。

2 个答案:

答案 0 :(得分:2)

您需要像使用paste一样创建列名,但是必须get来创建值,否则,您将保留并使用列名。我们还可以使用rowwise使过程每次都知道我们感兴趣的行:

library(tidyverse)

df = tribble(
  ~A, ~Y, ~V1, ~V2, ~V3,
  "One", 2, 89, 52, 37,
  "Two", 3, 45, 34, 86,
  "alpha", 1, 33, 36, 43,
  "beta", 1, 21, 33, 45,
  ) 

df %>% 
  rowwise() %>% 
  mutate(selectYCol = get(paste0("V", Y))) %>%
  ungroup()

# # A tibble: 4 x 6
#   A         Y    V1    V2    V3 selectYCol
#   <chr> <dbl> <dbl> <dbl> <dbl>      <dbl>
# 1 One       2    89    52    37         52
# 2 Two       3    45    34    86         86
# 3 alpha     1    33    36    43         33
# 4 beta      1    21    33    45         21

您还可以使用map2代替rowwisepull代替get,像这样:

df %>%
  nest(-A, -Y) %>%
  mutate(selectYCol = map2(Y, data, ~{.y %>% pull(paste0("V", .x))})) %>%
  unnest()

答案 1 :(得分:1)

另一种解决方法:

library(tidyverse)
tribble(
  ~A, ~Y, ~V1, ~V2, ~V3,
  "One", 2, 89, 52, 37,
  "Two", 3, 45, 34, 86,
  "alpha", 1, 33, 36, 43,
  "beta", 1, 21, 33, 45,
) -> df
df %>% gather(k,v,-A,-Y) %>%
  filter(paste0("V", Y)==k) %>%
  select(A,v) %>%
  inner_join(df,.,by="A")
## A tibble: 4 x 6
#  A         Y    V1    V2    V3     v
#  <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 One       2    89    52    37    52
#2 Two       3    45    34    86    86
#3 alpha     1    33    36    43    33
#4 beta      1    21    33    45    21