You can use match
. In case df$group
is a character (what is here the case) it could be directly used to subset the list.
df$value_l <- l[match(df$group, names(l))]
#df$value_l <- l[df$group] #Short alternative by @akrun works only in case df$group is a character, but not for factor or numeric
#df$value_l <- l[as.character(df$group)] #Maybe more secure
df
# group value value_l
#1 A 1 999
#2 B 2 55
#3 C 3 NULL
In case there is a need for NA
, instead of NULL
use in addition:
df$value_l[vapply(df$value_l, is.null, TRUE)] <- NA
df
# group value value_l
#1 A 1 999
#2 B 2 55
#3 C 3 NA
Or make it in single steps:
. <- match(df$group, names(l))
df$value_l <- l[.]
is.na(df$value_l) <- is.na(.)
Here we have joined a list
to a data.frame
.
str(df)
#'data.frame': 3 obs. of 3 variables:
# $ group : chr "A" "B" "C"
# $ value : num 1 2 3
# $ value_l:List of 3
# ..$ A : num 999
# ..$ B : num 55
# ..$ NA: logi NA
In case the List can be trasfomed to a vector you can use unlist
before (thanks to @G. Grothendieck for the comment). But here we have then joined a vector
to the data.frame
.
df$value_l <- unlist(l)[match(df$group, names(l))]
#df$value_l <- unlist(l)[as.character(df$group)] #Option like shown above
df
# group value value_l
#1 A 1 999
#2 B 2 55
#3 C 3 NA
str(df)
#'data.frame': 3 obs. of 3 variables:
# $ group : chr "A" "B" "C"
# $ value : num 1 2 3
# $ value_l: num 999 55 NA
Another option, also joined a vector
to the data.frame
will be using merge
.
merge(df, unlist(l), by.x="group", by.y=0, all.x = TRUE)
# group value y
#1 A 1 999
#2 B 2 55
#3 C 3 NA
Note: For the given list
the results look similar but this will not be the case if the list
looks e.g. like:
l <- list(A = 999, B = c(7, 55), A = 9)
A potential solution might be:
Taking first match:
df$value_l <- l[as.character(df$group)]
df
# group value value_l
#1 A 1 999
#2 B 2 7, 55
#3 C 3 NULL
Making a left Join
merge(df, list2DF(list(group = names(l), value_l = l)), all.x=TRUE)
#merge(df, data.frame(group = names(l), value_l = I(l)), all.x=TRUE) #Alternative
# group value value_l
#1 A 1 999
#2 A 1 9
#3 B 2 7, 55
#4 C 3 NA
Other options.
merge(df, list2DF(list(group = names(l), value_l = l))) #Inner
merge(df, list2DF(list(group = names(l), value_l = l)), all=TRUE) #Outer
merge(df, list2DF(list(group = names(l), value_l = l)), all.y=TRUE) #Right
For other options please have a look at How to join (merge) data frames (inner, outer, left, right).
list
to adata.frame
or is it also fine tounlist
the list to avector
and join it then? – Relucent