Преобразование вектора в формулу - PullRequest
0 голосов
/ 18 декабря 2018

Имеется только data.frame и вектор с -1,0,1, длина которого равна количеству столбцов data.frame.Есть ли естественный способ преобразовать вектор в формулу, где элементы с положением -1 появляются в левой части формулы, а элементы с +1 появляются справа?

Например, если заданоследующий data.frame

df = data.frame(
  'a' = rnorm(10),
  'b' = rnorm(10),
  'c' = rnorm(10),
  'd' = rnorm(10),
  'e' = rnorm(10))

и следующий вектор vec = c(-1,-1,0,1,1).

Есть ли естественный способ построения формулы a+b~d+e?

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Мы предполагаем, что если в vec нет 1, то мы должны использовать правую часть от 1, а если в vec нет -1, то левая сторона пуста.

Каждая из альтернатив создает строку символов, но если требуется объект класса формулы, используйте formula(s), где s - эта строка.

1) вставьте каждую сторону Подставьте имена, соответствующиеvec -1 дает LHS и вставляет / сворачивает их и делает то же самое с vec 1, давая RHS и вставляет их вместе с ~.Если бы мы знали, что в vec есть хотя бы один 1, мы могли бы опустить оператор if.Из представленных здесь решений это представляется наиболее простым.

nms <- names(df)
LHS <- paste(nms[vec == -1], collapse = "+")
RHS <- paste(nms[vec == 1], collapse = "+")
if (RHS == "") RHS <- "1"
paste0(LHS, "~", RHS)
## [1] "a+b~d+e"

2) sapply Альтернативно объедините линии LHS и RHS в одну sapply.Если бы мы знали, что в vec есть хотя бы один 1, то мы могли бы упростить код, пропустив оператор if.Этот подход короче (1).

sa <- sapply(c(-1, 1), function(x) paste(names(df)[vec == x], collapse = "+"))
if (sa[2] == "") sa[2] <- "1"
paste0(sa[1], "~", sa[2])
## [1] "a+b~d+e"

3) tapply Мы можем поочередно объединить линии LHS и RHS в одну tapply, например:

ta <- tapply(names(df), vec, paste, collapse = "+")
paste0(if (any(vec == -1)) ta[["-1"]], "~", if (any(vec == 1)) ta[["1"]] else 1)
## [1] "a+b~d+e"

Если мы знали, что -1 и 1 появляются по крайней мере один раз в vec, то мы можем упростить последнюю строку до:

paste0(ta[["-1"]], "~", ta[["1"]]])
## [1] "a+b~d+e"

В целом, этот подход самый короткий, если мы можем гарантировать, чтобудет по крайней мере один 1 и по крайней мере один -1, но в противном случае обработка краевых случаев кажется несколько громоздкой по сравнению с другими подходами.

0 голосов
/ 18 декабря 2018

Мы могли бы сделать это, создав группу paste

paste(aggregate(nm ~ vec, subset(data.frame(nm = names(df), vec, 
    stringsAsFactors = FALSE), vec != 0),
    FUN = paste, collapse= ' + ')[['nm']], collapse=' ~ ')
#[1] "a + b ~ d + e"

Или другой вариант tapply

paste(tapply(names(df), vec, FUN = paste, 
        collapse= ' + ')[c('-1', '1')], collapse= ' ~ ')
#[1] "a + b ~ d + e"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...