Хранение и вызов переменных в столбце в dplyr внутри функции - PullRequest
0 голосов
/ 29 января 2019

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

library("tidyverse") 
myData<-tibble("c1"=c("a","b","c"),
"c2"=c("1","2","3"),
"c3"=c("A","B","C"),
factors=c(list(c("c1","c2")),list(c("c2","c3")),list(c("c1","c2","c3"))))

myData%>%mutate(factors1=interaction(!!!quos(factors),sep=":",lex.order=TRUE))
# A tibble: 3 x 5
  c1    c2    c3    factors   factors1
  <chr> <chr> <chr> <list>    <fct>   
1 a     1     A     <chr [2]> c1:c2:c1
2 b     2     B     <chr [2]> c2:c3:c2
3 c     3     C     <chr [3]> c1:c2:c3

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

Для второй проблемы, в которой я хотел бы использовать столбец $ factor, чтобы специально вызывать значения другихстолбцы, я могу жестко закодировать это так:

myData%>%
mutate(factors2=interaction(!!!syms(c("c1","c2")),sep=":",lex.order=TRUE))
# A tibble: 3 x 5
 c1    c2    c3    factors   factors2
 <chr> <chr> <chr> <list>    <fct>   
1 a     1     A     <chr [2]> a:1     
2 b     2     B     <chr [2]> b:2     
3 c     3     C     <chr [3]> c:3  

Однако, если я попробую это:

myData%>%
mutate(factors2=interaction(!!!syms(factors),sep=":",lex.order=TRUE))

Error in lapply(.x, .f, ...) : object 'factors' not found

То же самое произойдет, если я попытаюсь отменить список факторов или использовать другие выражения rlang.Я также пытался вложить выражения rlang, но до сих пор не нашел того, который работает так, как я планировал.

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

Мой код полностью:

library("tidyverse") 

myData<-tibble("c1"=c("a","b","c"),
"c2"=c("1","2","3"),
"c3"=c("A","B","C"),
factors=c(list(c("c1","c2")),list(c("c2","c3")),list(c("c1","c2","c3"))))%>%
mutate(factors1=interaction(!!!quos(factors),sep=":",lex.order=TRUE))%>%
mutate(factors2=interaction(!!!syms(factors),sep=":",lex.order=TRUE))

Мой желаемый вывод:

    # A tibble: 3 x 6
 c1    c2    c3    factors   factors1   factors2
 <chr> <chr> <chr> <list>     <fct>      <fct>   
1 a     1     A     <chr [2]> c1:c2       a:1     
2 b     2     B     <chr [2]> c2:c3       2:B     
3 c     3     C     <chr [3]> c1:c2:c3    c:3:C  

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Вот метод, использующий map и imap:

library(tidyverse)

myData %>%
  mutate(factor1 = factors %>% map(~interaction(as.list(.), sep=':', lex.order = TRUE)) %>% unlist(),
         factor2 = factors %>% imap(~interaction(myData[.y, match(.x, names(myData))], sep=":", lex.order = TRUE)) %>% unlist())

Для factor1, вместо объединения аргументов в точки, я передаю список в interaction.

Для factor2 я сопоставляю factors в каждой строке с names в myData и использует индекс столбца (match(.x, names(myData))) в сочетании с индексом строки (.y из imap)для подстановки соответствующих элементов для подачи в interaction.

Для factor1 и factor2 требуется unlist, поскольку map и imap возвращают списки.

Вывод:

# A tibble: 3 x 6
  c1    c2    c3    factors   factor1  factor2
  <chr> <chr> <chr> <list>    <fct>    <fct>  
1 a     1     A     <chr [2]> c1:c2    a:1    
2 b     2     B     <chr [2]> c2:c3    2:B    
3 c     3     C     <chr [3]> c1:c2:c3 c:3:C  
0 голосов
/ 30 января 2019

Ваш первый вопрос может быть решен с помощью purrr::map и purrr::lift семейств функций:

myData %>%
  mutate( factors1 = map(factors, lift_dv(interaction, sep=":", lex.order=TRUE)) ) %>%
  mutate_at( "factors1", lift(fct_c) )
# # A tibble: 3 x 5
#   c1    c2    c3    factors   factors1
#   <chr> <chr> <chr> <list>    <fct>
# 1 a     1     A     <chr [2]> c1:c2
# 2 b     2     B     <chr [2]> c2:c3
# 3 c     3     C     <chr [3]> c1:c2:c3

Второй вопрос более сложный, поскольку !!! вызывает немедленную оценку его аргумента, чтоиногда может привести к неинтуитивному приоритету оператора внутри цепочки dplyr.Самый простой способ - определить автономную функцию, которая будет составлять ваши interaction выражения:

f <- function(fct) {expr( interaction(!!!syms(fct), sep=":", lex.order=TRUE) )}

# Example usage
f( myData$factors[[1]] )    # interaction(c1, c2, sep = ":", lex.order = TRUE)
f( myData$factors[[2]] )    # interaction(c2, c3, sep = ":", lex.order = TRUE)

myData %>% mutate( e = map(factors, f) )
# # A tibble: 3 x 5
#   c1    c2    c3    factors   e
#   <chr> <chr> <chr> <list>    <list>
# 1 a     1     A     <chr [2]> <language>
# 2 b     2     B     <chr [2]> <language>
# 3 c     3     C     <chr [3]> <language>

К сожалению, мы не можем напрямую оценить e, поскольку она будет кормить все столбцы c1, c2 и c3 для выражений, тогда как вам нужно только одно значение, которое находится в той же строке, что и выражение.По этой причине нам нужно инкапсулировать столбцы с c1 по c3 построчно.

X <- myData %>% mutate( e = map(factors, f) ) %>%
  rowwise() %>% mutate( d = list(data_frame(c1,c2,c3)) ) %>% ungroup()
# # A tibble: 3 x 6
#   c1    c2    c3    factors   e          d
#   <chr> <chr> <chr> <list>    <list>     <list>
# 1 a     1     A     <chr [2]> <language> <tibble [1 × 3]>
# 2 b     2     B     <chr [2]> <language> <tibble [1 × 3]>
# 3 c     3     C     <chr [3]> <language> <tibble [1 × 3]>

Теперь у вас есть выражения в e, которые необходимо применить к данным в d, так что это просто map2 обход отсюда.Собрав все воедино и убрав, мы получим:

myData %>%
  mutate( factors1 = map(factors, lift_dv(interaction, sep=":", lex.order=TRUE)) ) %>%
  mutate( e = map(factors, f) ) %>%
  rowwise() %>% mutate( d = list(data_frame(c1,c2,c3)) ) %>% ungroup() %>%
  mutate( factors2 = map2( e, d, rlang::eval_tidy ) ) %>%
  mutate_at( vars(factors1,factors2), lift(fct_c) ) %>%
  select( -e, -d )
# # A tibble: 3 x 6
#   c1    c2    c3    factors   factors1 factors2
#   <chr> <chr> <chr> <list>    <fct>    <fct>
# 1 a     1     A     <chr [2]> c1:c2    a:1
# 2 b     2     B     <chr [2]> c2:c3    2:B
# 3 c     3     C     <chr [3]> c1:c2:c3 c:3:C
...