r dplyr mutate_if несколько условий - PullRequest
0 голосов
/ 06 марта 2020

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

Вот мои данные:

structure(list(ph503_3 = c(-1, -1, -1, 0, -1, -1), gripstrength = c(33, 
40, 26, 30, 49, 31), IPAQmetminutes = c(5196, 198, 1674, 642, 
11724, 1155), tugtimesec = c(8, 7, 7, 17, 9, 8), MHcesd = c(1, 
0, 1, 12, 0, 9), id = c("292221", "334262", "075822", "40642", 
"274222", "245801"), age = c(58, 68, 54, 64, 52, 58), COGmmse = c(30, 
27, 29, 27, 30, 29), DISconverse1 = c("None", "None", "None", 
"None", "None", "None"), MDantidepressant = c("No", "No", "No", 
"Yes", "No", "No"), MDantipark = c(0, 0, 0, 0, 0, 0), MDpolypharmacy = c(0, 
0, 0, 1, 0, 0), W2socialclass = c("Skilled", "Semi-skilled", 
"Managerial & Technical", "Non-Manual", "Skilled", "Managerial & Technical"
), bh201 = c("Would never doze", "Would never doze", "Slight chance of dozing", 
"Would never doze", "High chance of dozing", "Would never doze"
), fl001_01 = c("NOT Walking 100 metres (100 yards)", "NOT Walking 100 metres (100 yards)", 
"NOT Walking 100 metres (100 yards)", "Walking 100 metres (100 yards)", 
"NOT Walking 100 metres (100 yards)", "NOT Walking 100 metres (100 yards)"
), fl001_02 = c("NOT Running or jogging about 1.5 kilometres (1 mile)", 
"Running or jogging about 1.5 kilometres (1 mile)", "NOT Running or jogging about 1.5 kilometres (1 mile)", 
"Running or jogging about 1.5 kilometres (1 mile)", "Running or jogging about 1.5 kilometres (1 mile)", 
"NOT Running or jogging about 1.5 kilometres (1 mile)"), fl001_04 = c("NOT Getting up from a chair after sitting for long periods", 
"NOT Getting up from a chair after sitting for long periods", 
"NOT Getting up from a chair after sitting for long periods", 
"Getting up from a chair after sitting for long periods", "NOT Getting up from a chair after sitting for long periods", 
"NOT Getting up from a chair after sitting for long periods"), 
    fl001_05 = c("NOT Climbing several flights of stairs without resting", 
    "NOT Climbing several flights of stairs without resting", 
    "NOT Climbing several flights of stairs without resting", 
    "Climbing several flights of stairs without resting", "NOT Climbing several flights of stairs without resting", 
    "NOT Climbing several flights of stairs without resting"), 
    fl001_06 = c("NOT Climbing one flight of stairs without resting", 
    "NOT Climbing one flight of stairs without resting", "NOT Climbing one flight of stairs without resting", 
    "Climbing one flight of stairs without resting", "NOT Climbing one flight of stairs without resting", 
    "NOT Climbing one flight of stairs without resting"), fl001_07 = c("NOT Stooping, kneeling, or crouching", 
    "NOT Stooping, kneeling, or crouching", "NOT Stooping, kneeling, or crouching", 
    "Stooping, kneeling, or crouching", "NOT Stooping, kneeling, or crouching", 
    "NOT Stooping, kneeling, or crouching")), row.names = c(NA, 
-6L), class = c("tbl_df", "tbl", "data.frame"))

Мой код:

mydata <- mydata %>% 
  mutate_if(class(.)=="character" & str_detect(colnames(.), "^fl\\d|^ph\\d"), ~if_else(grepl("NOT ", .), 0, 1)) 

Код выполняется, но ничего не происходит, и я получаю следующее сообщение, когда связываю уценку:

Warning message:
In class(.) == "character" & str_detect(colnames(.), "^fl\\d|^ph\\d") :
  longer object length is not a multiple of shorter object length

1 Ответ

2 голосов
/ 06 марта 2020

Условие должно возвращать несколько столбцов одновременно, но чтение class(.) == "character" заставляет меня поверить, что вы проверяете один столбец за раз. . заменяется внутри всего кадра, а не отдельных столбцов / векторов. Вторая половина вашего условия корректна, но первая:

myfunc <- function(...) { browser(); TRUE; }
mydata %>% mutate_if(myfunc(.), ~ 1)
# Browse[2]>
list(...)
# [[1]]
# # A tibble: 6 x 20
#   ph503_3 gripstrength IPAQmetminutes tugtimesec MHcesd id      age COGmmse DISconverse1
#     <dbl>        <dbl>          <dbl>      <dbl>  <dbl> <chr> <dbl>   <dbl> <chr>       
# 1      -1           33           5196          8      1 2922~    58      30 None        
# 2      -1           40            198          7      0 3342~    68      27 None        
# 3      -1           26           1674          7      1 0758~    54      29 None        
# 4       0           30            642         17     12 40642    64      27 None        
# 5      -1           49          11724          9      0 2742~    52      30 None        
# 6      -1           31           1155          8      9 2458~    58      29 None        
# # ... with 11 more variables: MDantidepressant <chr>, MDantipark <dbl>, MDpolypharmacy <dbl>,
# #   W2socialclass <chr>, bh201 <chr>, fl001_01 <chr>, fl001_02 <chr>, fl001_04 <chr>,
# #   fl001_05 <chr>, fl001_06 <chr>, fl001_07 <chr>

В этом контексте class(whole_data_frame) == "character" не имеет смысла (само по себе).

Вы можете искать символьные столбцы используя sapply(., is.character) (или один из purrr эквивалентов):

mydata %>% 
  mutate_if(sapply(., is.character) &
              stringr::str_detect(colnames(.), "^fl\\d|^ph\\d"),
            ~ +(!grepl("NOT ", .))) %>%
  str(.)
# Classes 'tbl_df', 'tbl' and 'data.frame': 6 obs. of  20 variables:
#  $ ph503_3         : num  -1 -1 -1 0 -1 -1
#  $ gripstrength    : num  33 40 26 30 49 31
#  $ IPAQmetminutes  : num  5196 198 1674 642 11724 ...
#  $ tugtimesec      : num  8 7 7 17 9 8
#  $ MHcesd          : num  1 0 1 12 0 9
#  $ id              : chr  "292221" "334262" "075822" "40642" ...
#  $ age             : num  58 68 54 64 52 58
#  $ COGmmse         : num  30 27 29 27 30 29
#  $ DISconverse1    : chr  "None" "None" "None" "None" ...
#  $ MDantidepressant: chr  "No" "No" "No" "Yes" ...
#  $ MDantipark      : num  0 0 0 0 0 0
#  $ MDpolypharmacy  : num  0 0 0 1 0 0
#  $ W2socialclass   : chr  "Skilled" "Semi-skilled" "Managerial & Technical" "Non-Manual" ...
#  $ bh201           : chr  "Would never doze" "Would never doze" "Slight chance of dozing" "Would never doze" ...
#  $ fl001_01        : int  0 0 0 1 0 0
#  $ fl001_02        : int  0 1 0 1 1 0
#  $ fl001_04        : int  0 0 0 1 0 0
#  $ fl001_05        : int  0 0 0 1 0 0
#  $ fl001_06        : int  0 0 0 1 0 0
#  $ fl001_07        : int  0 0 0 1 0 0

(я сократил ваш if_else(grepl("NOT ", .), 0, 1) до +(!grepl("NOT ", .)), немного для code-golf, немного потому, что я Подумайте, используя ifelse / if_else, это немного больше, чем необходимо. Это не так, и если ваши будущие потребности немного сложнее, чем просто 0 / 1, тогда if_else, безусловно, хорошо. трюк с +(...) - это способ быстро преобразовать логическое в целое число, попробуйте +TRUE.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...