2017-02-19 24 views
0

Учитывая эти данные:dplyr: мутировать новый столбец на основе нескольких столбцов, выбранных переменной строкой

df=data.frame(
    x1=c(2,0,0,NA,0,1,1,NA,0,1), 
    x2=c(3,2,NA,5,3,2,NA,NA,4,5), 
    x3=c(0,1,0,1,3,0,NA,NA,0,1), 
    x4=c(1,0,NA,3,0,0,NA,0,0,1), 
    x5=c(1,1,NA,1,3,4,NA,3,3,1)) 

Я хочу, чтобы создать дополнительный столбец min для построчно минимального значения выбранных столбцов с помощью dplyr. Это легко, используя имена столбцов:

df <- df %>% rowwise() %>% mutate(min = min(x2,x5)) 

Но у меня есть большой ДФ с различными именами столбцов, поэтому мне нужно, чтобы сопоставить их с некоторой строки значений mycols. Теперь другие потоки говорят мне использовать вспомогательные функции select, но я должен что-то пропускать. Вот matches:

mycols <- c("x2","x5") 
df <- df %>% rowwise() %>% 
    mutate(min = min(select(matches(mycols)))) 
Error: is.string(match) is not TRUE 

one_of И:

mycols <- c("x2","x5") 
df <- df %>% 
rowwise() %>% 
mutate(min = min(select(one_of(mycols)))) 
Error: no applicable method for 'select' applied to an object of class "c('integer', 'numeric')" 
In addition: Warning message: 
In one_of(c("x2", "x5")) : Unknown variables: `x2`, `x5` 

Что я с видом? Должно ли select_ работать? Это не в следующем:

df <- df %>% 
    rowwise() %>% 
    mutate(min = min(select_(mycols))) 
Error: no applicable method for 'select_' applied to an object of class "character" 

и также:

df <- df %>% 
    rowwise() %>% 
    mutate(min = min(select_(matches(mycols)))) 
Error: is.string(match) is not TRUE 
+0

Вы должны использовать SE версии dplyr глаголов при использовании строк. В этом случае используйте 'select_()' –

+0

Не работает так, как я ожидал, что он будет работать: 'df <- df %>% rowwise()%>% mutate (min = min (select_ (mycols)))' yields "Error : no применимый метод для 'select_', примененный к объекту класса "character" " – strangeloop

+0

Вы получаете ошибку с' match', поскольку она принимает строку (regex) как аргумент, а не вектор строки. – cderv

ответ

1

Это было немного сложнее. В случае SE-оценки вам необходимо передать операцию как строку.

mycols <- '(x2,x5)' 
f <- paste0('min',mycols) 
df %>% rowwise() %>% mutate_(min = f) 
df 
# A tibble: 10 × 6 
#  x1 x2 x3 x4 x5 min 
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
#1  2  3  0  1  1  1 
#2  0  2  1  0  1  1 
#3  0 NA  0 NA NA NA 
#4  NA  5  1  3  1  1 
#5  0  3  3  0  3  3 
#6  1  2  0  0  4  2 
#7  1 NA NA NA NA NA 
#8  NA NA NA  0  3 NA 
#9  0  4  0  0  3  3 
#10  1  5  1  1  1  1 
+1

Спасибо! Теперь я хочу наименьшее значение, отличное от NA, поэтому мне нужно немного изменить этот код. Кажется, что он изменился с 'min' на' pmin (na.rm = T) 'works (добавление na.rm = T в' min() 'похоже не работает): ' f <- paste0 ('pmin (', mycols,', na.rm = T) ') ' ' df <- df %>% rowwise()%>% mutate_ (min = f) ' – strangeloop

3

Вот еще одно решение немного техническим с помощью purrr пакета из tidyverse предназначен для функционального программирования.

Кулак, matches Помощники от dplyr принимает строку регулярных выражений как аргумент, а не вектор. Это хороший способ найти регулярное выражение, соответствующее всем вашим столбцам. (в коде под вы можете использовать dplyr выбора помощника, который вы хотите)

Затем purrr функции прекрасно работает с dplyr, когда вы понимаете основную схему программирования Функциональное.

Решение вашей проблемы:


df=data.frame(
    x1=c(2,0,0,NA,0,1,1,NA,0,1), 
    x2=c(3,2,NA,5,3,2,NA,NA,4,5), 
    x3=c(0,1,0,1,3,0,NA,NA,0,1), 
    x4=c(1,0,NA,3,0,0,NA,0,0,1), 
    x5=c(1,1,NA,1,3,4,NA,3,3,1)) 


# regex to get only x2 and x5 column 
mycols <- "x[25]" 

library(dplyr) 

df %>% 
    mutate(min_x2_x5 = 
      # select columns that you want in df 
      select(., matches(mycols)) %>% 
      # use pmap on this subset to get a vector of min from each row. 
      # dataframe is a list so pmap works on each element of the list that is to say each row 
      purrr::pmap_dbl(min) 
     ) 
#> x1 x2 x3 x4 x5 min_x2_x5 
#> 1 2 3 0 1 1   1 
#> 2 0 2 1 0 1   1 
#> 3 0 NA 0 NA NA  NA 
#> 4 NA 5 1 3 1   1 
#> 5 0 3 3 0 3   3 
#> 6 1 2 0 0 4   2 
#> 7 1 NA NA NA NA  NA 
#> 8 NA NA NA 0 3  NA 
#> 9 0 4 0 0 3   3 
#> 10 1 5 1 1 1   1 

Я не буду объяснять дальше о purrr здесь, но он отлично работает в вашем случае