Search code examples
rloopsdata-manipulationdata-cleaning

referencing vector names dynamically via strings contained in another vector


A data frame HAVE contains a vector of identifiers called partner whose values are identical to other vector names in that data frame.

HAVE:

id  partner met id1 id2 id3 id4 id5 id6 id7 id8 id9 id10
id1  id10   1   NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id2  id6    0   NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id3  id7    0   NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id4  id9    1   NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id5  id8    1   NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id6  NA     NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id7  NA     NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id8  NA     NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id9  NA     NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id10 NA     NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA

Another vector met indicates whether or not the respondent represented by id for each observation met up with their assigned partner. I need to store the value for met in the correct column id1-id10, where the column name is equivalent to partner. For example, the first observation should include a value of 1 in the column id10.

WANT:

id  partner met id1 id2 id3 id4 id5 id6 id7 id8 id9 id10
id1  id10   1   NA  NA  NA  NA  NA  NA  NA  NA  NA  1
id2  id6    0   NA  NA  NA  NA  NA  0   NA  NA  NA  NA
id3  id7    0   NA  NA  NA  NA  NA  NA  0   NA  NA  NA
id4  id9    1   NA  NA  NA  NA  NA  NA  NA  NA  1   NA
id5  id8    1   NA  NA  NA  NA  NA  NA  NA  1   NA  NA
id6  NA     NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id7  NA     NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id8  NA     NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id9  NA     NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
id10 NA     NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA

How can I use the value of a text variable to systematically assign values to variables with names that match the other variable's value? The true set includes id1-id100; here's a link to data for a miniature example.


Solution

  • Here is an option with vectorized indexing. Get the column index with match with the column names and the 'partner' column, cbind with row sequence to create a matrix, extract the elements of the dataset based on the index and assign it to 'met' column

    nm1 <- grep("^id\\d+$", names(df1))
    i1 <- !is.na(df1$partner)
    df1[nm1][cbind(seq_len(nrow(df1))[i1],
          match(df1$partner[i1], names(df1)[nm1]))] <- df1$met[i1]
    df1
    #     id partner met id1 id2 id3 id4 id5 id6 id7 id8 id9 id10
    #1   id1    id10   1  NA  NA  NA  NA  NA  NA  NA  NA  NA    1
    #2   id2     id6   0  NA  NA  NA  NA  NA   0  NA  NA  NA   NA
    #3   id3     id7   0  NA  NA  NA  NA  NA  NA   0  NA  NA   NA
    #4   id4     id9   1  NA  NA  NA  NA  NA  NA  NA  NA   1   NA
    #5   id5     id8   1  NA  NA  NA  NA  NA  NA  NA   1  NA   NA
    #6   id6    <NA>  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA   NA
    #7   id7    <NA>  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA   NA
    #8   id8    <NA>  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA   NA
    #9   id9    <NA>  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA   NA
    #10 id10    <NA>  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA   NA
    

    data

    df1 <- structure(list(id = c("id1", "id2", "id3", "id4", "id5", "id6", 
    "id7", "id8", "id9", "id10"), partner = c("id10", "id6", "id7", 
    "id9", "id8", NA, NA, NA, NA, NA), met = c(1L, 0L, 0L, 1L, 1L, 
    NA, NA, NA, NA, NA), id1 = c(NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, NA), id2 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), id3 = c(NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA), id4 = c(NA, NA, NA, NA, 
    NA, NA, NA, NA, NA, NA), id5 = c(NA, NA, NA, NA, NA, NA, NA, 
    NA, NA, NA), id6 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), 
        id7 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), id8 = c(NA, 
        NA, NA, NA, NA, NA, NA, NA, NA, NA), id9 = c(NA, NA, NA, 
        NA, NA, NA, NA, NA, NA, NA), id10 = c(NA, NA, NA, NA, NA, 
        NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, 
    -10L))