【问题标题】:Looping over a vector and check for existence of data.frames with the same name循环一个向量并检查是否存在同名的data.frames
【发布时间】:2016-09-09 09:58:40
【问题描述】:

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

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

这给了

表格 [1] “ttest” “ttest2” “mtcars”

然后我开始循环

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")))}

这总是返回“表...未找到”。虽然 mtcars 是一个现有的 data.frame。我可以改变什么来使它工作? 谢谢!

【问题讨论】:

    标签: r loops dataframe


    【解决方案1】:

    您可以将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 解析树) .

    在您的代码中,您使用as.name()tables[i] 中的字符串值强制转换为符号类型,然后将生成的符号对象传递给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() 来说明您走在正确的轨道上。

    【讨论】:

    • 非常感谢,这显然有效。有趣的是,我也尝试过使用 eval,但我没有想到将这两个表达式结合起来 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 2019-04-28
    • 1970-01-01
    • 2021-01-10
    相关资源
    最近更新 更多