将列表连接到R中的 Dataframe

smdncfj3  于 2023-01-18  发布在  其他
关注(0)|答案(5)|浏览(135)

我有以下 Dataframe df和列表l(dput如下):

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

$B
[1] 55

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

group value value_l
1     A     1     999
2     B     2      55
3     C     3      NA

所以我想知道是否有人知道如何根据名字将列表加入数据框?
dput方向角和长度:

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)
lb3vh1jj

lb3vh1jj1#

你可以使用match。如果df$group是一个 * 字符 *(这里就是这种情况),它可以直接用于列表的子集。

df$value_l <- l[match(df$group, names(l))]
#df$value_l <- l[df$group]  #Short alternative by @arkun 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

如果需要使用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

或者一步到位:

. <- match(df$group, names(l))
df$value_l <- l[.]
is.na(df$value_l) <- is.na(.)

这里,我们 * 将list连接到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

如果列表可以转换成向量,你可以使用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

另一个选项,也加入了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

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

l <- list(A = 999, B = c(7, 55), A = 9)

一种可能的解决办法是:
获取第一个匹配项:

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

进行 * 左连接 *

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

其他选择。

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

有关其他选项,请查看How to join (merge) data frames (inner, outer, left, right)

ldxq2e6h

ldxq2e6h2#

使用base R中的merge

merge(df, stack(l), by.x = 'group', by.y = 'ind', all.x = TRUE)
  group value values
1     A     1    999
2     B     2     55
3     C     3     NA

或使用dplyr

library(dplyr)
df %>%
   rowwise %>%
   mutate(value_l = if(group %in% names(l)) l[[group]] else NA) %>% 
   ungroup
  • 输出
# A tibble: 3 × 3
  group value value_l
  <chr> <dbl>   <dbl>
1 A         1     999
2 B         2      55
3 C         3      NA

或者使用enframe/unnest

library(tidyr)
library(tibble)
enframe(l, name = 'group', value = 'value_l') %>%
  unnest(value_l) %>% 
  left_join(df, .)
  group value value_l
1     A     1     999
2     B     2      55
3     C     3      NA

或者它是否可以是列表列

df$value_l <- l[df$group]
> df
  group value value_l
1     A     1     999
2     B     2      55
3     C     3    NULL
u91tlkcl

u91tlkcl3#

您可以:

library(tidyverse)

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

其给出:

group value value_1
1     A     1     999
2     B     2      55
3     C     3      NA
pkwftd7m

pkwftd7m4#

    • 更新日期:**

也许这个:

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
    • 第一个答案:**略有不同:

x一个一个一个一个x一个一个二个x

b1uwtaje

b1uwtaje5#

这是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

对于单线解决方案,如果没有中间变量:

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

df
  group value l_value
1     A     1     999
2     B     2      55
3     C     3      NA

根据您需要列表的其他用途,甚至可以在第一个位置使用命名向量而不是列表。

相关问题