#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