将列表连接到 R 中的数据框

Qui*_*ten 12 join r list dataframe

我有以下数据框 df 和列表 l (dput如下):

> df
  group value
1     A     1
2     B     2
3     C     3
> l
$A
[1] 999

$B
[1] 55
Run Code Online (Sandbox Code Playgroud)

我想根据列表中的名称与数据帧的组变量将列表的值连接到数据帧,并将其称为“value_l”。预期输出应如下所示:

  group value value_l
1     A     1     999
2     B     2      55
3     C     3      NA
Run Code Online (Sandbox Code Playgroud)

所以我想知道是否有人知道如何根据他们的名字将列表加入到数据框?


dputdf 和 l:

df <- structure(list(group = c("A", "B", "C"), value = c(1, 2, 3)), class = "data.frame", row.names = c(NA, 
-3L))
l <- list(A = 999, B = 55)
Run Code Online (Sandbox Code Playgroud)

GKi*_*GKi 10

您可以使用match。如果 casedf$group是一个字符(这里的情况是什么),它可以直接用于列表的子集。

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
Run Code Online (Sandbox Code Playgroud)

如果需要NA, 而不是NULL另外使用:

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
Run Code Online (Sandbox Code Playgroud)

或者通过以下步骤完成:

. <- match(df$group, names(l))
df$value_l <- l[.]
is.na(df$value_l) <- is.na(.)
Run Code Online (Sandbox Code Playgroud)

这里我们加入了 alist到 adata.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
Run Code Online (Sandbox Code Playgroud)

如果列表可以转换为unlist之前可以使用的向量(感谢@G. Grothendieck 的评论)。但在这里我们加入了vector一个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
Run Code Online (Sandbox Code Playgroud)

另一个选项,也加入了vectordata.frame要使用的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
Run Code Online (Sandbox Code Playgroud)

注意:对于给定的结果看起来相似,但如果看起来像list这样,则情况并非如此:list

l <- list(A = 999, B = c(7, 55), A = 9)
Run Code Online (Sandbox Code Playgroud)

一个潜在的解决方案可能是:
进行第一场比赛:

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
Run Code Online (Sandbox Code Playgroud)

进行左连接

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
Run Code Online (Sandbox Code Playgroud)

其他选择。

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
Run Code Online (Sandbox Code Playgroud)

对于其他选项,请查看如何连接(合并)数据框(内部、外部、左、右)


des*_*hen 6

你可以做:

library(tidyverse)

l |> 
  as.data.frame() |> 
  pivot_longer(cols      = everything(),
               names_to  = "group",
               values_to = "value_1") |> 
  left_join(x  = df,
            y  = _,
            by = "group")
Run Code Online (Sandbox Code Playgroud)

这使:

  group value value_1
1     A     1     999
2     B     2      55
3     C     3      NA
Run Code Online (Sandbox Code Playgroud)


akr*_*run 6

使用merge来自base R

\n
 merge(df, stack(l), by.x = 'group', by.y = 'ind', all.x = TRUE)\n  group value values\n1     A     1    999\n2     B     2     55\n3     C     3     NA\n
Run Code Online (Sandbox Code Playgroud)\n
\n

或者与dplyr

\n
library(dplyr)\ndf %>%\n   rowwise %>%\n   mutate(value_l = if(group %in% names(l)) l[[group]] else NA) %>% \n   ungroup\n
Run Code Online (Sandbox Code Playgroud)\n

-输出

\n
# A tibble: 3 \xc3\x97 3\n  group value value_l\n  <chr> <dbl>   <dbl>\n1 A         1     999\n2 B         2      55\n3 C         3      NA\n
Run Code Online (Sandbox Code Playgroud)\n
\n

或者使用enframe/unnest

\n
library(tidyr)\nlibrary(tibble)\nenframe(l, name = 'group', value = 'value_l') %>%\n  unnest(value_l) %>% \n  left_join(df, .)\n  group value value_l\n1     A     1     999\n2     B     2      55\n3     C     3      NA\n
Run Code Online (Sandbox Code Playgroud)\n
\n

或者如果它可以是列表列

\n
df$value_l <- l[df$group]\n> df\n  group value value_l\n1     A     1     999\n2     B     2      55\n3     C     3    NULL\n
Run Code Online (Sandbox Code Playgroud)\n


Tar*_*Jae 5

更新:

也许是这个:

library(dplyr)

stack(unlist(l)) %>% 
  full_join(df, by=c("ind"="group"))

  values ind value
1    999   A     1
2     55   B     2
3     NA   C     3 
Run Code Online (Sandbox Code Playgroud)

第一个答案: 略有不同:

library(dplyr)
library(tidyr)
bind_rows(l) %>% 
  pivot_longer(everything()) %>% 
  full_join(df, by=c("name"="group")) %>% 
  select(name, value = value.y, value_l=value.x)
Run Code Online (Sandbox Code Playgroud)
 name  value value_l
  <chr> <dbl>   <dbl>
1 A         1     999
2 B         2      55
3 C         3      NA
Run Code Online (Sandbox Code Playgroud)


anj*_*ama 5

这是 GKi 建议的更简单的版本unlist()。如果您的列表始终具有名称和单个数值,您可以将其转换为命名向量,然后将其用作查找向量,这比执行合并或匹配更简单:

temp_vec = unlist(l)
df$l_value = temp_vec[df$group]

df
  group value l_value
1     A     1     999
2     B     2      55
3     C     3      NA
Run Code Online (Sandbox Code Playgroud)

没有单行解决方案的中间变量:

df$l_value = unlist(l)[df$group]

df
  group value l_value
1     A     1     999
2     B     2      55
3     C     3      NA
Run Code Online (Sandbox Code Playgroud)

根据您需要列表的其他用途,甚至首先使用命名向量而不是列表可能是有意义的。