简体   繁体   中英

Conditionally take value from column1 if the column1 name == first(value) from column2 BY GROUP

I have this fake dataframe:

df <- structure(list(Group = c(1L, 1L, 2L, 2L), A = 1:4, B = 5:8, C = 9:12, 
X = c("A", "A", "B", "B")), class = "data.frame", row.names = c(NA, -4L))

  Group A B  C X
1     1 1 5  9 A
2     1 2 6 10 A
3     2 3 7 11 B
4     2 4 8 12 B

I try to mutate a new column, which should take the value of THE column that has the column name in an other column:

Desired output:

Group   A   B   C   X new_col
1       1   5   9     A 1
1       2   6   10    A 1
2       3   7   11    B 7
2       4   8   12    B 7

My try so far:

library(dplyr)

df %>% 
  group_by(Group) %>% 
  mutate(across(c(A,B,C), ~ifelse(first(X) %in% colnames(.), first(.), .), .names = "new_{.col}"))

  Group     A     B     C X     new_A new_B new_C
  <int> <int> <int> <int> <chr> <int> <int> <int>
1     1     1     5     9 A         1     5     9
2     1     2     6    10 A         1     5     9
3     2     3     7    11 B         3     7    11
4     2     4     8    12 B         3     7    11

One option might be:

df %>%
    rowwise() %>%
    mutate(new_col = get(X)) %>%
    group_by(Group, X) %>%
    mutate(new_col = first(new_col))

 Group     A     B     C X     new_col
  <int> <int> <int> <int> <chr>   <int>
1     1     1     5     9 A           1
2     1     2     6    10 A           1
3     2     3     7    11 B           7
4     2     4     8    12 B           7

Using by and add + 1 to the group number to select column. Assuming group columns are arranged as in example after "Group" column.

transform(df, new_col=do.call(rbind, by(df, df$Group, \(x) 
                                        cbind(paste(x$X, x[1, x$Group[1] + 1])))))
#   Group A B  C X new_col
# 1     1 1 5  9 A     A 1
# 2     1 2 6 10 A     A 1
# 3     2 3 7 11 B     B 7
# 4     2 4 8 12 B     B 7
          

Note: R version 4.1.2 (2021-11-01) .


Data:

df <- structure(list(Group = c(1L, 1L, 2L, 2L), A = 1:4, B = 5:8, C = 9:12, 
    X = c("A", "A", "B", "B")), class = "data.frame", row.names = c(NA, 
-4L))

In base R , we may use row/column indexing

df$new_col <- df[2:4][cbind(match(unique(df$Group), df$Group)[df$Group], 
       match(df$X, names(df)[2:4]))]
df$new_col
[1] 1 1 7 7

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM