循环向量并检查是否存在具有相同名称的data.frames

时间:2016-05-13 09:17:31

标签: r loops dataframe

如标题中所述,我试图遍历包含字符串的向量,这可能是或可能是data.frames的名称。它不需要是矢量,实际上它是一个data.frame,我提取了一列。 这是我尝试过的:

tables <- as.vector(df.stattributes.run[,1])

这给出了

  

表   [1]&#34; ttest&#34; &#34; ttest2&#34; &#34; mtcars&#34;

然后我开始循环

for (i in 1:length(tables))
  {try(if(!is.data.frame(as.name(tables[i])) == TRUE) stop(paste("Table",tables[i],"doesn't exist.")) else print(paste("Table",tables[i],"found")))}

这总是会回复&#34;表...没找到。&#34;虽然mtcars是现有的data.frame。我可以改变什么来使它工作? 谢谢!

1 个答案:

答案 0 :(得分:5)

您可以将mget()inherits=Tifnotfound=list(NULL)(或任何非data.frame值)一起使用,并将is.data.frame()应用于每个:

sapply(mget(tables,inherits=T,ifnotfound=list(NULL)),is.data.frame);
##  ttest ttest2 mtcars
##  FALSE  FALSE   TRUE

此处需要inherits=T的原因是mtcars不在全局环境中,这是mget()在顶层运行时默认显示的位置。它实际上驻留在内置数据集包的公共环境中。您可以使用find()来标识对象所在的位置:

find('mtcars');
## [1] "package:datasets"

另外,我应该在这里解决一些误解。 as.name()函数与as.symbol()完全等效。这些函数将给定参数强制转换为符号类型。

符号类型是R语言本身的R表示的一部分,或者换句话说是R语法树的表示,使用R数据类型。换句话说,你可能会说它是R的R数据模型的一部分。有关这方面的更多信息,请参阅我的答案here

大多数时候,大多数R程序员不需要使用符号,因为他们不需要“在语言上计算”,因为它经常被调用(意味着他们不需要操作R解析树)

在您的代码中,您使用tables[i]as.name()中的字符串值强制转换为符号类型,然后将生成的符号对象传递给is.data.frame()。这是不正确的。在符号对象上调用is.data.frame()将始终返回false,因为符号不是data.frame。通常,is.*函数适用于给定对象的类型;他们做任何“解决”或“查找”或“搜索”以找到论证所指的最终对象;参数 is.*函数进行类型测试的对象。

第二点,您不需要== TRUE。如果你已经有一个逻辑值,那么它已经是真的,在这种情况下,比较将保持为真,或者它已经是假的,在这种情况下,比较会将其保留为假(或者它已经是NA) ,在这种情况下,比较会将其保留为NA)。

有趣的是,在写完上面的解释后,我意识到有一种替代方法可以获得一个名称存储在字符串值中的对象,它确实涉及as.symbol() / as.name()功能我上面有点不屑一顾。我在谈论在符号对象上调用eval()

head(eval(as.symbol(tables[3L])));
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
is.data.frame(eval(as.symbol(tables[3L])));
## [1] TRUE

因此,我们实际上可以通过致电as.name()来说您走在正确的轨道上。