根据另一个列表提取数据

Extract data based on another list

我正在尝试根据嵌套在个体中的时间点列表提取数据集的行。我有重复的时间点(因此变量值完全相同)但我仍然想保留重复的行。如何在 base R 中实现?

这是原始数据集:

xx <- data.frame(id=rep(1:3, each=3), time=1:3, y=rep(1:3, each=3))

这是矩阵列表,其中第三个是向量

lst <- list(`1` = c(1, 1, 2), `2` = c(1, 3, 3), `3` = c(2, 2, 3))

理想的结果:

id time y
 1    1 1
 1    1 1  #this is the duplicated row
 1    2 1
 2    1 2
 2    3 2
 2    3 2 #this is the duplicated row
 3    2 3
 3    2 3 #this is the duplicated row
 3    3 3

代码 do.call(rbind, Map(function(p, q) subset(xx, id == q & time %in% p), lst, names(lst))) 对我不起作用,因为 subset 删除了重复的行

问题是 %in% 不会重复遍历 non-unique 值。为此,我们还需要在内部对 p 进行迭代 (lapply)。我会将你内心的 subset 包裹在另一个 do.call(rbind, lapply(p, ...)) 中以获得你所期望的:

do.call(rbind, Map(function(p, q) {
  do.call(rbind, lapply(p, function(p0) subset(xx, id == q & time %in% p0))) 
  }, lst, names(lst)))
#      id time y
# 1.1   1    1 1
# 1.2   1    1 1
# 1.21  1    2 1
# 2.4   2    1 2
# 2.6   2    3 2
# 2.61  2    3 2
# 3.8   3    2 3
# 3.81  3    2 3
# 3.9   3    3 3

(行名在这里会让人分心...)

另一种方法是将您的 lst 转换为 idtime 的框架,然后在其上 left-join:

frm <- do.call(rbind, Map(function(x, nm) data.frame(id = nm, time = x), lst, names(lst)))
frm
#     id time
# 1.1  1    1
# 1.2  1    1
# 1.3  1    2
# 2.1  2    1
# 2.2  2    3
# 2.3  2    3
# 3.1  3    2
# 3.2  3    2
# 3.3  3    3

merge(frm, xx, by = c("id", "time"), all.x = TRUE)
#   id time y
# 1  1    1 1
# 2  1    1 1
# 3  1    2 1
# 4  2    1 2
# 5  2    3 2
# 6  2    3 2
# 7  3    2 3
# 8  3    2 3
# 9  3    3 3

学习 merges/joins 的两个好资源:

  • How to join (merge) data frames (inner, outer, left, right)
  • What's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN?