В R использовать функцию ls() с регулярным выражением для сохранения только символьных объектов?

#r #regex

#r #регулярное выражение

Вопрос:

Я создал более 100 объектов, каждый из которых состоит из двух символьных строк. Все они начинаются со знака равенства, например,

 intro <- c("=intro", "For calendar year 2007 blah blah.")

 str(intro)
 chr [1:2] "=intro" ...
  

Моя цель — объединить все эти объекты в фрейм данных, который содержит первую часть, которой предшествует «=» в первом столбце, и вторую часть, предложение или предложения, во втором столбце.

Чтобы сохранить все объекты в виде фрейма данных:

 character.objects <- data.frame(chrobjects = ls(), stringsAsFactors = FALSE) 
  

Есть ли способ использовать аргумент pattern = функции ls, чтобы во фрейме данных character.objects сохранялись только объекты chr [1:2]? Или как еще я могу достичь своей цели?

Комментарии:

1. Некоторый контекст был бы хорош. Что это за язык?

2. Как называются ваши объекты, подобные intro ? Существует ли какая-либо согласованность или аналогичная схема именования?

3. Никакой согласованности, за исключением того, что в них нет знаков препинания и все они состоят из одного слова. Я думал о добавлении «txt» в начало их, но это означает более 220 изменений вручную.

Ответ №1:

Прежде всего, создание такого набора переменных, вероятно, не является хорошей стратегией проектирования. Скорее всего, эти значения следует объединить в список или что-то в этом роде. Но один из способов найти имена всех таких переменных —

 whatIwant<-function(x) {
    z <- get(x)
    if (is.character(z)) {
        if (length(z)==2) {
            if (substr(z[1],1,1)=="=")
                return(TRUE)
        }
    }
    return(FALSE)
}

myvars <- Filter(whatIwant, ls())
  

Таким образом, ls() возвращает символьный вектор с именами всех объектов в вашей рабочей области. Я использую Filter , чтобы сократить этот список только до интересующих нас имен. Я написал пользовательскую функцию whatIwant , чтобы помочь найти эти значения.

Вспомогательная функция использует имена из ls() , а затем фактически получает объект через get() . Затем мы проверяем класс, длину и значения, чтобы убедиться, что они соответствуют вашим критериям. Таким образом, myvars должен быть символьный вектор только с именами переменных, которые соответствуют вашему описанию

И затем мы можем превратить этот вектор имен переменных в data.frame, содержащий их значения, с помощью чего-то вроде

 do.call(rbind, lapply(mget(myvars), function(x) data.frame(key=x[1], val=x[2])))
  

или, может быть

 myvals <- mget(myvars)
data.frame(key=sapply(myvals, `[`, 1), val=sapply(myvals, `[`, 2))
  

Обратите внимание, что в этом решении не используется pattern= параметр ls() функции, поскольку этот параметр работает только с именем объектов, а не с содержимым или типом самих объектов.

Комментарии:

1. Мистер Флик, я испытываю благоговейный трепет и стесняюсь комментировать, потому что я не понимаю функцию Filter и то, что она возвращает функцию myvars. Я запустил do.call и ошибка в get(myvars) : неверный первый аргумент. Я не знаю, с чего начать, чтобы разобраться в этом.

2. @user2583119 Я обновил ответ, включив дополнительные детали. Я бы проверил значение myvars после выполнения Filter шага. Оно должно содержать все имена объектов, которые вы хотите объединить. Выглядит ли это разумно?

3. Это работает идеально. У меня были некоторые помехи от предыдущей работы. Как только я очистил свои объекты и начал заново, все было в порядке. Теперь, чтобы узнать о get(), Filter() и do.call()! Спасибо

4. Вы можете немного уменьшить «рабочую нагрузку», используя мою lsclass функцию (пакет cgwtools ) . Filter(whatIwant,lsclass('character') .

Ответ №2:

Вы тоже могли бы попробовать.

Создание некоторых данных

 intro <- c("=intro", "For calendar year 2007 blah blah.")
intro1 <- c("intro", "For calendar year 2008 blah blah.")
intro2 <- c("intro=", "For calendar year 2009 blah blah.")
intro3 <- c("=intro", "For calendar year 2010 blah")

library(stringr)
res <- do.call(rbind, lapply(mget(ls())[sapply(mget(ls()), is.character)], function(x) {
x1 <- x[str_detect(x, perl("(?<=^=)[[:alnum:]] "))[1]]
if (length(x1) > 0) 
    data.frame(key = x1[1], val = x1[2], stringsAsFactors = F)
}))

res
#         key                               val
#intro  =intro For calendar year 2007 blah blah.
#intro3 =intro       For calendar year 2010 blah