Неэффективно ли писать код R, который косвенно ссылается на переменные, чтобы обойти жесткое кодирование? - PullRequest
2 голосов
/ 07 июня 2019

Допустим, у меня есть кадр данных ниже:

x <- data.frame(id= c("a", "b", "c", "d", "e")
                , term= c(179, 192, 189, 182, 179)
                , f17= c(1, 2, 3, 4, 5)
                , s18= c(6, 7, 8, 9, 10)
                , f18 = c(11, 12, 13, 14, 15)
                , s19 = c(16, 17, 18, 19, 20))

В этом фрейме данных я хочу создать переменную, которая записывает значение для каждого идентификатора из соответствующего столбца для данного термина (f17 соответствует термину 179, s18 соответствует термину 182, f18 соответствует термину 189, f19 соответствует до срока 192).

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

Я относительно новичок в R, но я очень опытный программист макросов SAS и SAS, поэтому я знаю, что в SAS то, что я хочу сделать, можно очень легко сделать с помощью пары массивов и цикла do в шаге данных и это то, что я по сути пытаюсь воссоздать в R. То, что я в итоге сделал, было следующим:

ПРИМЕЧАНИЕ: я понимаю, что то, что ниже, не то же самое, что серия вложенных операторов ifelse, а вместо этого - последовательность операторов ifelse для того, чтобы перезаписывать одну и ту же переменную, но это действительно дает мне решение, которое я нужно, учитывая все случаи в моих данных.

xTerms <- c(179, 182, 189, 192)
xVars <- c("f17", "s18", "f18", "s19")

x$startVal <- NA
for(i in 1:length(xTerms)){
  x$startVal <- ifelse(x$term == xTerms[i], x[[xVars[i]]], x$startVal)
}

Я должен добавить, это желаемый результат:

> x
  id term f17 s18 f18 s19 startVal
1  a  179   1   6  11  16        1
2  b  192   2   7  12  17       17
3  c  189   3   8  13  18       13
4  d  182   4   9  14  19        9
5  e  179   5  10  15  20        5

Идея с кодом выше заключается в том, что когда я получаю новые данные, мне просто нужно обновить определения xTerms и xVars. Или я мог бы даже создать их динамически на основе уникального списка значений термина переменная в x и переменных в x.

Мне любопытно получить отзывы от более опытных пользователей R, если это лучший способ решения подобных итерационных проблем в R? Есть ли ресурсы, которыми вы можете поделиться о том, как сделать что-то такое, что лучше использует R?

Ответы [ 3 ]

2 голосов
/ 07 июня 2019

Если вы поместите xTerms и xVars в таблицу поиска lkp, вы можете преобразовать свои данные в длинную форму с помощью melt и соединиться с lkp, чтобы получить начальные значения. Затем вы можете присоединиться к x, чтобы добавить его в качестве столбца.

library(data.table)
setDT(x)

lkp <- data.table(Terms = xTerms, Vars = xVars)

startvals <- melt(x, c('id', 'term'))[lkp, on = .(term == Terms, variable == Vars)]

x[startvals, on = .(id, term), startVal := value]


x  
#    id term f17 s18 f18 s19 startVal
# 1:  a  179   1   6  11  16        1
# 2:  b  192   2   7  12  17       17
# 3:  c  189   3   8  13  18       13
# 4:  d  182   4   9  14  19        9
# 5:  e  179   5  10  15  20        5
2 голосов
/ 07 июня 2019

Вы можете использовать match ...

xTerms <- c(179, 182, 189, 192)
xVars <- c("f17", "s18", "f18", "s19")

x$startVal <- sapply(1:nrow(x), function(i) x[i, xVars[match(x$term[i], xTerms)]])

x
  id term f17 s18 f18 s19 startVal
1  a  179   1   6  11  16        1
2  b  192   2   7  12  17       17
3  c  189   3   8  13  18       13
4  d  182   4   9  14  19        9
5  e  179   5  10  15  20        5
1 голос
/ 07 июня 2019

Можно использовать row/column индексирование

x$startVal <- x[3:6][cbind(seq_len(nrow(x)), 
             match(xVars[match(x$term, xTerms)], names(x)[3:6]))]
x
#  id term f17 s18 f18 s19 startVal
#1  a  179   1   6  11  16        1
#2  b  192   2   7  12  17       17
#3  c  189   3   8  13  18       13
#4  d  182   4   9  14  19        9
#5  e  179   5  10  15  20        5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...