How can I use one column to determine where I get the value for another column?

前端 未结 3 1981
伪装坚强ぢ
伪装坚强ぢ 2021-01-25 15:33

I\'m trying to use one column to determine which column to use as the value for another column It looks something like this:

     X   Y  Z   Target
1    a   b           


        
相关标签:
3条回答
  • 2021-01-25 16:07
    library(tidyverse)
    
    df <-setNames(data.frame(cbind(matrix(letters[1:9],3,3,byrow=T), c("X", "Y", "Z"))), c("X", "Y", "Z", "Target"))
    
    df
    
    df %>% 
      gather(key="ID", value="TargetValue", X:Z) %>%
      filter(ID==Target) %>%
      select(Target, TargetValue) %>%
      left_join(df, by="Target")
    
    0 讨论(0)
  • 2021-01-25 16:11

    You could try apply rowwise like this:

    transform(df, TargetValue = apply(df, 1, function(x) x[x["Target"]]))
    #   X Y Z Target TargetValue
    # 1 a b c      X           a
    # 2 d e f      Y           e
    # 3 g h i      Z           i
    
    0 讨论(0)
  • 2021-01-25 16:19

    A vectorized approach would be to use matrix subsetting:

    df %>% mutate(TargetValue = .[cbind(1:n(), match(Target, names(.)))])
    #  X Y Z Target TargetValue
    #1 a b c      X           a
    #2 d e f      Y           e
    #3 g h i      Z           i
    

    Or just using base R (same approach):

    transform(df, TargetValue = df[cbind(1:nrow(df), match(Target, names(df)))])
    

    Explanation:

    • match(Target, names(.)) computes the column indices of the entries in Target (which column is called X etc)
    • The . in the dplyr version refers to the data you "pipe" into the mutate statement with %>% (i.e. it refers to df)
    • df[cbind(1:n(), match(Target, names(df))] creates a matrix to subset df to the correct values - the first column of the matrix is just the row numbers starting from 1 to the number of rows of df (therefore 1:nrow(df)) and the second column in the matrix is the index which column holds the Target value of interest (computed by match(Target, names(df))).

    The matrix that is produced for subsetting the example data is:

    cbind(1:nrow(df), match(df$Target, names(df)))
         [,1] [,2]
    [1,]    1    1
    [2,]    2    2
    [3,]    3    3
    
    0 讨论(0)
提交回复
热议问题