Hiding function names from ls() results - to find a variable name more quickly

痴心易碎 提交于 2019-12-04 09:08:12

If you want a function to do this, you need to play around a bit with the environment that ls() looks in. In normal usage, the implementation below will work by listing objects in the parent frame of the function, which will be the global environment if called at the top level.

lsnofun <- function(name = parent.frame()) {
    obj <- ls(name = name)
    obj[!sapply(obj, function(x) is.function(get(x)))]
}

> ls()
[1] "bar"           "crossvalidate" "df"           
[4] "f1"            "f2"            "foo"          
[7] "lsnofun"       "prod"         
> lsnofun()
[1] "crossvalidate" "df"            "f1"           
[4] "f2"            "foo"           "prod"

I've written this so you can pass in the name argument of ls() if you need to call this way down in a series of nested function calls.

Note also we need to get() the objects named by ls() when we test if they are a function or not.

Rather than sorting through the objects in your global environment and trying to seperate data objects from functions it would be better to store the functions in a different environment so that ls() does not list them (by default it only lists things in the global environment). But they are still accessible and can be listed if desired.

The best way to do this is to make a package with the functions in it. This is not as hard as it sometimes seems, just use package.skeleton to start.

Another alternative is to use the save function to save all your functions to a file, delete them from the global environment, then use the attach function to attach this file (and therefore all the functions) to the search path.

So perhaps

ls()[!ls()%in%lsf.str()]

Josh O'Brien's suggestion was to use

setdiff(ls(), lsf.str())

That function, after some conversions and checks, calls

x[match(x, y, 0L) == 0L]

which is pretty close to what I suggested in the first place, but is packed nicely in the function setdiff.

Marc in the box

The following function lsos was previously posted on stackoverflow (link) - it gives a nice ordering of objects loaded in your R session based on their size. The output of the function contains the class of the object, which you can subsequently filter to get the non-function objects.

source("lsos.R")

A <- 1
B <- 1
C <- 1
D <- 1
E <- 1
F <- function(x) print(x)

L <- lsos(n=Inf)
L[L$Type != "function",]

This returns:

> lsos(n=Inf)
         Type Size Rows Columns
lsos function 5184   NA      NA
F    function 1280   NA      NA
A     numeric   48    1      NA
B     numeric   48    1      NA
C     numeric   48    1      NA
D     numeric   48    1      NA
E     numeric   48    1      NA

Or, with the filter, the function F is not returned:

> L[L$Type != "function",]
     Type Size Rows Columns
A numeric   48    1      NA
B numeric   48    1      NA
C numeric   48    1      NA
D numeric   48    1      NA
E numeric   48    1      NA
nograpes

So you just want the variable names, not the functions? This will do that.

ls()[!sapply(ls(), function(x) is.function(get(x)))]

I keep this function in my .rprofile. I don't use it often but it's great when I have several environments, function and objects in my global environment. Clearly not as elegant as BenBarnes' solution but I never have to remember the syntax and can just call lsa() as needed. This also allows me to list specific environments. e.g. lsa(e)

lsa <- function(envir = .GlobalEnv) {
    obj_type <- function(x) {
        class(get(x))
    }
    lis <- data.frame(sapply(ls(envir = envir), obj_type))
    lis$object_name <- rownames(lis)
    names(lis)[1] <- "class"
    names(lis)[2] <- "object"
    return(unrowname(lis))
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!