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)
另一个选项,也加入了vector将data.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)
对于其他选项,请查看如何连接(合并)数据框(内部、外部、左、右)。
你可以做:
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)
使用merge来自base R
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\nRun Code Online (Sandbox Code Playgroud)\n或者与dplyr
library(dplyr)\ndf %>%\n rowwise %>%\n mutate(value_l = if(group %in% names(l)) l[[group]] else NA) %>% \n ungroup\nRun 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\nRun Code Online (Sandbox Code Playgroud)\n或者使用enframe/unnest
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\nRun Code Online (Sandbox Code Playgroud)\n或者如果它可以是列表列
\ndf$value_l <- l[df$group]\n> df\n group value value_l\n1 A 1 999\n2 B 2 55\n3 C 3 NULL\nRun Code Online (Sandbox Code Playgroud)\n
更新:
也许是这个:
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)
这是 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)
根据您需要列表的其他用途,甚至首先使用命名向量而不是列表可能是有意义的。