Renaming list elements by key with dataframe

Viewed 38

I have a list that looks like this:

$fec9
[1] "yes"

$`39c1`
[1] "no"

$d387
[1] "yes"

$`0065`
[1] "yes"

and a dataframe that has matching keys to the list's elements as such:

dataframe <- data.frame(key = c('39c1', 'fec9', 'p731' '0065', 'd387'),
                        label = c('trash', 'wash car', 'cook dinner', 'mow lawn', 'vacuum'))

I am trying to rename each element in the list the corresponding key's label but the data frame is not in the same order as the list and there are some keys in the dataframe that do not appear in the list. currently I am trying:

for(i in names(list)){
  names(list[i]) <- dataframe %>% filter(key == names(list[i])) %>% select(label)
}

However when I inspect the list after the names have all remained the same

3 Answers

I hope you are looking for this:

#method 1
#get common key from dataframe
df <- df[df$key %in% names(list), ]
list <- list[df$key] #getting the same order as of dataframe
names(list) <- df$label

#method 2
#if you want to preserve the order of labels: 
df <- df[df$key %in% names(list), ]
row.names(df) <- df$key
names(list) <- df[names(list), ]$label

Data

list <- list(fec9 = 'yes', `39c1` = 'no', 'd387' = 'yes', `0065` = 'yes')
df <- data.frame(key = c('39c1', 'fec9', 'p731', '0065', 'd387'),  
                        label = c('trash', 'wash car', 'cook dinner', 'mow lawn', 'vacuum'), stringsAsFactors = FALSE)

Output from the second method:

$`wash car`
[1] "yes"

$trash
[1] "no"

$vacuum
[1] "yes"

$`mow lawn`
[1] "yes"

Assuming the columns of data.frame are character, then we get the intersecting elements of names of 'list' and the 'key' and use that to assign the list values with the corresponding 'label'

nm1 <- intersect(names(list), dataframe$key)
list[nm1] <- dataframe$label[dataframe$key %in% nm1]

data

list <- list(fec9 = 'yes', `39c1` = 'no', 'd387' = 'yes', `0065` = 'yes')
dataframe <- data.frame(key = c('39c1', 'fec9', 'p731', '0065', 'd387'),  
           label = c('trash', 'wash car', 'cook dinner', 'mow lawn', 'vacuum'))

Here is a base R option using merge + stack + setNames

with(
  merge(stack(lst), df, by.x = "ind", by.y = "key"),
  setNames(as.list(values), label)
)

which gives

$`mow lawn`
[1] "yes"

$trash
[1] "no"

$vacuum
[1] "yes"

$`wash car`
[1] "yes"

Data

> dput(lst)
list(fec9 = "yes", `39c1` = "no", d387 = "yes", `0065` = "yes")

> dput(df)
structure(list(key = c("39c1", "fec9", "p731", "0065", "d387"
), label = c("trash", "wash car", "cook dinner", "mow lawn",
"vacuum")), class = "data.frame", row.names = c(NA, -5L))
Related