在列表中操作data.frame时,有什么方法可以方便输出?

时间:2016-10-12 10:45:24

标签: r list dataframe dplyr

我在列表中有data.frame对象,这些对象也以所需的方式进行操作以进行进一步处理。但是,我打算将每个列表的补充集给定条件,我也只是简单地绘制辅助函数来执行此任务。我使用dplyr包中的setdiff函数,我敢打赌这是正确的方法。但输出结果不是我的预期。我尝试了一种使用辅助函数进行嵌套列表的可能方法,但是如果我更改了参数(type = c(“Bio”,“Tech”)),则输出不正确。有没有快速的方法来获得我期望的干净,结构良好的输出?我怎样才能做到这一点?有什么想法吗?

快速可重复的例子:

savedList <- list(
  foo_saved = data.frame(v1=c(1,6,16), v2=c(4,12,23), nm=c("a1","a2","a3")),
  bar_saved = data.frame(v1=c(7,19,31), v2=c(13,28,43), nm=c("b3","b6","b7")),
  cat_saved = data.frame(v1=c(5,21,36), v2=c(11,29,42), nm=c("c2","c4","c9"))
)

dropedList <- list(
  foo_droped = data.frame(v1=c(6,25,40), v2=c(12,33,49),nm=c("a2","a5","a8")),
  bar_droped = data.frame(v1=c(15,19,47), v2=c(18,28,55),nm=c("b4","b6","b9")),
  cat_droped = data.frame(v1=c(13,21,36,53), v2=c(19,29,42,67),nm=c("c3","c4","c9","c12"))
)

我用这个技巧来操纵列表:

x <- c(savedList, dropedList)
newList <- split(x, sub("_.*", "", names(x)))[sub("_.*", "", names(savedList))]

这是我打算实现的辅助函数:

func <- function(list, type=c("Bio", "Tech")) {
  type=match.arg(type)
  if(type=="Bio") list[[1]] else setdiff(list[[1]], list[[2]])
}

我这样做可能实现我的输出:

res <- Map(func, newList)

但如果我将类型设置为“Tech”,则此功能无效,setdiff无法返回我预期的补充设置。如果我使用Map,更改类型并获得不同的输出也有点困难。有没有有效的方法来获得我想要的输出?

然后我想有条件地对每个列表进行补充。

如果类型为“Bio”,则需要输出:

output.Bio <- list(
  foo_otp = data.frame(v1=c(1,6,16), v2=c(4,12,23), nm=c("a1","a2","a3")),
  bar_otp = data.frame(v1=c(7,19,31), v2=c(13,28,43), nm=c("b3","b6","b7")),
  cat_otp = data.frame(v1=c(5,21,36), v2=c(11,29,42), nm=c("c2","c4","c9"))
)

如果type为“Tech”,则需要输出:

output.Tech <- list(
  foo_otp = data.frame(v1=c(1,16),v2=c(4,23),nm=c("a1","a3")),
  bar_otp = data.frame(v1=c(7,31),v2=c(13,43),nm=c("b3","b7")),
  cat_otp = data.frame(v1=c(5),v2=(11),nm="c2")
)

我无法弄清楚辅助函数出了什么问题。有什么建议可以确保帮助函数以更安全的方式工作吗?如何才能完成此任务以更有效地获得所需的输出?非常感谢

1 个答案:

答案 0 :(得分:1)

您正在研究data.frame之间的区别,anti_join来自dplyr的{​​{1}}。这将为您提供output.Tech

Map(anti_join, savedList, dropedList)

#Joining by: c("v1", "v2", "nm")
#Joining by: c("v1", "v2", "nm")
#Joining by: c("v1", "v2", "nm")
#$foo_saved
#  v1 v2 nm
#1 16 23 a3
#2  1  4 a1

#$bar_saved
#  v1 v2 nm
#1  7 13 b3
#2 31 43 b7

#$cat_saved
#  v1 v2 nm
#1  5 11 c2

如果您想将这段代码合并到您的代码中,只需创建一个简单的函数:

func = function(L1, L2, type)
{
    if(!type %in% c('Bio','Tech')) stop('Wrong type')
    if(type=='Bio') return(L1)
    Map(anti_join, L1, L2)
}

#func(savedList, dropedList, 'Tech')
#func(savedList, dropedList, 'Bio')