这是一个难题。
假设您有一个数据框和一个列表。列表中的元素与df中的行一样多:
dd <- data.frame(ID=1:3, Name=LETTERS[1:3])
dl <- map(4:6, rnorm) %>% set_names(letters[1:3])
Run Code Online (Sandbox Code Playgroud)
是否有一种简单的方法(最好使用dplyr / tidyverse)来制作长格式,以使列表中的元素与数据帧的相应行连接在一起?这是我心目中不太优雅的方式:
rows <- map(1:length(dl), ~ rep(., length(dl[[.]]))) %>% unlist()
dd <- dd[rows,]
dd$value <- unlist(dl)
Run Code Online (Sandbox Code Playgroud)
如您所见,对于中的每个向量dl,我们都会根据需要将对应的行复制多次,以容纳每个值。
Cat*_*ath 10
在基地R,你可以得到你的结果stack之后merge:
res <- merge(stack(dl), dd, by.x="ind", by.y="Name")
head(res)
# ind values ID
#1 A -0.79616693 1
#2 A 0.37720953 1
#3 A 1.30273712 1
#4 A 0.19483859 1
#5 B 0.18770716 2
#6 B -0.02226917 2
Run Code Online (Sandbox Code Playgroud)
注意:我以为名称dl应该是大写的,但是如果它们确实是小写的,则需要改用以下行:
res <- merge(stack(setNames(dl, toupper(names(dl)))), dd, by.x="ind", by.y="Name")
Run Code Online (Sandbox Code Playgroud)
由于已经提供了dplyr解决方案,因此另一个选择是在使用data.table分组时dl对每个Name值进行子集化dd
library(data.table)
setDT(dd)
dd[, .(values = dl[[tolower(Name)]]), by = .(ID, Name)]
# ID Name values
# 1: 1 A -1.09633600
# 2: 1 A -1.26238190
# 3: 1 A 1.15220845
# 4: 1 A -1.45741071
# 5: 2 B -0.49318131
# 6: 2 B 0.59912670
# 7: 2 B -0.73117632
# 8: 2 B -1.09646143
# 9: 2 B -0.79409753
# 10: 3 C -0.08205888
# 11: 3 C 0.21503398
# 12: 3 C -1.17541571
# 13: 3 C -0.10020616
# 14: 3 C -1.01152362
# 15: 3 C -1.03693337
Run Code Online (Sandbox Code Playgroud)
我们可以创建一个list列unnest
library(tidyverse)
dd %>%
mutate(value = dl) %>%
unnest
# ID Name value
#1 1 A 1.57984385
#2 1 A 0.66831102
#3 1 A -0.45472145
#4 1 A 2.33807619
#5 2 B 1.56716709
#6 2 B 0.74982763
#7 2 B 0.07025534
#8 2 B 1.31174561
#9 2 B 0.57901536
#10 3 C -1.36629653
#11 3 C -0.66437155
#12 3 C 2.12506187
#13 3 C 1.20220402
#14 3 C 0.10687018
#15 3 C 0.15973401
Run Code Online (Sandbox Code Playgroud)
请注意,如果条件基于代码的紧凑性,则如果删除 %>%
unnest(mutate(dd, value = dl))
Run Code Online (Sandbox Code Playgroud)
或者另一个选择是uncount和mutate
dd %>%
uncount(lengths(dl)) %>%
mutate(value = flatten_dbl(unname(dl)))
Run Code Online (Sandbox Code Playgroud)
如果需要基于“ dl”名称的联接
enframe(dl, name = 'Name') %>%
mutate(Name = toupper(Name)) %>%
left_join(dd) %>%
unnest
Run Code Online (Sandbox Code Playgroud)
在中base R,我们可以rep将'dd'与lengths'dl' 的行连接起来,transform并将'value'创建为ed'dl unlist'
transform(dd[rep(seq_len(nrow(dd)), lengths(dl)),], value = unlist(dl))
Run Code Online (Sandbox Code Playgroud)