在R中,如何根据函数内部的值列表正确地对数据框进行子集化?

时间:2018-03-06 21:52:35

标签: r parsing dataframe subset eval

我有一个函数试图根据值列表从数据框中选择行。

例如,某些值可能是:

> subset_ids
[1] "JUL_0003_rep1" "JUL_0003_rep2"
[3] "JUL_0003_rep3" "JUL_0007_rep1"
[5] "JUL_0007_rep2" "JUL_0007_rep3" 

我有一个名为"目标"的数据框。使用名为" LongName"的列。它有许多其他专栏但没什么大不了的。当LongName在子集ID中时,我想从目标中选择行。

我可以用以下任何一种方法做到这一点:

targets[is.element(targets$LongName, subset_ids),]

targets[targets$LongName %in% subset_ids,]

问题是我想在一个函数中执行此操作,并且我不知道该列将被提前调用。

所以我尝试使用eval / parse方法,在最近阅读时可能不是最好的方法。当我执行以下操作时:

sub1 <- paste("targets[is.element(targets$", column_name, ", subset_ids),]", sep="")
targets_subset <- as.character(eval(parse(text = sub1)))

它返回一些奇怪的行号连接。它看起来像这样:

[1] "c(5, 6, 7, 17, 18, 19, 26, 27, 28, 35, 36, 46, 47, 48, 54, 55, 61, 62, 63, 64, 73, 74, 75, 76, 77, 78, 91, 92, 93, 102, 103, 104, 114, 117, 118, 129, 136, 137, 140, 141, 151, 152, 153, 157, 158, 159, 169, 172, 173, 183, 187, 188, 199, 200, 201, 208, 209, 210, 232, 233, 241, 242, 243, 252, 253, 254, 264, 265, 270, 271, 285, 286, 296, 297, 298)"
[2] "c(5, 6, 7, 17, 18, 19, 26, 27, 28, 35, 36, 46, 47, 48, 54, 55, 61, 62, 63, 64, 73, 74, 75, 76, 77, 78, 91, 92, 93, 102, 103, 104, 114, 117, 118, 129, 136, 137, 140, 141, 151, 152, 153, 157, 158, 159, 169, 172, 173, 183, 187, 188, 199, 200, 201, 208, 209, 210, 232, 233, 241, 242, 243, 252, 253, 254, 264, 265, 270, 271, 285, 286, 296, 297, 298)"
[3] "c(3, 3, 3, 7, 7, 7, 11, 11, 11, 15, 15, 19, 19, 19, 22, 22, 26, 26, 27, 27, 31, 31, 31, 32, 32, 32, 39, 39, 39, 43, 43, 43, 47, 49, 49, 53, 57, 57, 59, 59, 63, 63, 63, 65, 65, 65, 70, 72, 72, 76, 78, 78, 83, 83, 83, 86, 86, 86, 97, 97, 100, 100, 100, 104, 104, 104, 108, 108, 111, 111, 117, 117, 121, 121, 121)" 

所以5,6,7,17​​ ......似乎是我试图选择的目标的正确行,但我不明白为什么它首先发送回来,或者是什么项目[3]。

如果我手动执行上述&#34; sub1&lt; - ...&#34;生成的行,则返回正确的数据。如果我要求函数执行此操作,它将返回此垃圾。

我的问题是双重的。 1:为什么数据以这种方式返回? 2:有没有比eval / parse更好的方法去做我想做的事情?

我怀疑是一些奇怪的范围或环境问题,但目前我还不清楚。我感谢任何人的建议。

1 个答案:

答案 0 :(得分:1)

以这种方式返回数据,因为您正在将数据帧强制转换为字符对象。尝试

as.character(head(targets))

看一个简短的例子。

因此,如果消除as.character(),您的方法就有效。这是一个MWE:

targets <- data.frame(LongName = sample(letters, 1000, replace = TRUE),
                      SeqNum= 1:1000,
                      X = rnorm(1000))
subset_ids <- c("a","f")

targets[is.element(targets$LongName, subset_ids),]

targets[targets$LongName %in% subset_ids,]

testfun <- function(targets, column_name, subset_ids){
  sub1 <- paste("targets[is.element(targets$", column_name, ", subset_ids),]", sep="")
  targets_subset <- eval(parse(text = sub1))

  return(targets_subset)
}

testfun(targets, column_name = "LongName", subset_ids)