dplyr mutate - как передать одну строку в качестве аргумента функции?

Я пытаюсь создать новый столбец в моей таблице, который собирает и форматирует все слова, найденные во всех других столбцах. Я хотел бы сделать это с помощью dplyr, если это возможно. Исходный DataFrame:

df <- read.table(text =      "  columnA     columnB      
                 1            A           Z                    
                 2            B           Y                    
                 3            C           X                    
                 4            D           W                    
                 5            E           V                   
                 6            F           U            "  ) 

В качестве упрощенного примера я надеюсь сделать что-то вроде:

df %>%
    rowwise() %>%
    mutate(newColumn = myFunc(.))

И вывод будет выглядеть так:

       columnA     columnB      newColumn
1            A           Z             AZ        
2            B           Y             BY        
3            C           X             CX        
4            D           W             DW        
5            E           V             EV        
6            F           U             FU       

Когда я пытаюсь это сделать в своем коде, вывод выглядит так:

       columnA     columnB      newColumn
1            A           Z             ABCDEF        
2            B           Y             ABCDEF        
3            C           X             ABCDEF    
4            D           W             ABCDEF    
5            E           V             ABCDEF    
6            F           U             ABCDEF

myFunc должен взять одну строку в качестве аргумента, но когда я пытаюсь использовать rowwise(), мне кажется, что я передаю всю функцию в функцию (я вижу это, добавив функцию печати в myFunc).

Как я могу передать только одну строку и сделать это итеративно, чтобы она применяла функцию к каждой строке? Можно ли это сделать с помощью dplyr?

Редактировать:

myFunc в примере упрощен ради моего вопроса. Фактическая функция выглядит так:

get_chr_vector <- function(row) {

    row <- row[,2:ncol(row)] # I need to skip the first row
    words <- str_c(row, collapse = ' ')
    words <- str_to_upper(words)
    words <- unlist(str_split(words, ' '))
    words <- words[words != '']
    words <- words[!nchar(words) <= 2]
    words <- removeWords(words, stopwords_list) # from the tm library
    words <- paste(words, sep = ' ', collapse = ' ')
}

2 ответа

Решение

Взгляни на ?dplyr::do а также ?purrr::map, которые позволяют применять произвольные функции к произвольным столбцам и связывать результаты через несколько унарных операторов. Например,

df1 <- df %>% rowwise %>% do( X = as_data_frame(.) ) %>% ungroup
# # A tibble: 6 x 1
#                  X
# *           <list>
# 1 <tibble [1 x 2]>
# 2 <tibble [1 x 2]>
# ...

Обратите внимание на этот столбец X теперь содержит 1x2 data.frameс (или tibbles) состоит из строк из вашего оригинала data.frame, Теперь вы можете передать каждый на свой заказ myFunc с помощью map,

myFunc <- function(Y) {paste0( Y$columnA, Y$columnB )}
df1 %>% mutate( Result = map(X, myFunc) )
# # A tibble: 6 x 2
#                  X    Result
#             <list>    <list>
# 1 <tibble [1 x 2]> <chr [1]>
# 2 <tibble [1 x 2]> <chr [1]>
# ...

Result столбец теперь содержит вывод myFunc применяется к каждой строке в вашем оригинале data.frame, по желанию. Вы можете получить значения путем объединения tidyr::unnest операция.

df1 %>% mutate( Result = map(X, myFunc) ) %>% unnest
# # A tibble: 6 x 3
#   Result columnA columnB
#    <chr>  <fctr>  <fctr>
# 1     AZ       A       Z
# 2     BY       B       Y
# 3     CX       C       X
# ...

При желании unnest может быть ограничено конкретными столбцами, например, unnest(Result),

РЕДАКТИРОВАТЬ: потому что ваш оригинал data.frame содержит только два столбца, вы можете пропустить do шаг и использование purrr::map2 вместо. Синтаксис очень похож на map:

myFunc <- function( a, b ) {paste0(a,b)}
df %>% mutate( Result = map2( columnA, columnB, myFunc ) )

Обратите внимание, что myFunc теперь определяется как двоичная функция.

Это должно работать

   df <- read.table(text =      "  columnA     columnB      
                 1            A           Z                    
                 2            B           Y                    
                 3            C           X                    
                 4            D           W                    
                 5            E           V                   
                 6            F           U            "  )  

df %>%
  mutate(mutate_Func = paste0(columnA,columnB))

   columnA columnB mutate_Func
1       A       Z          AZ
2       B       Y          BY
3       C       X          CX
4       D       W          DW
5       E       V          EV
6       F       U          FU
Другие вопросы по тегам