Замена отсутствующих значений в R значениями, полученными из имен столбцов, если они не отсутствуют, с использованием mutate_at - PullRequest
0 голосов
/ 10 июля 2020

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

Примеры данных:

s <- data.frame(Finch=c(1, 5, NA, 2), 
            Station_1_Finch=c(NA, NA, NA, NA), 
            Station_2_Finch=c(NA, NA, 60, NA), 
            Station_3_Finch=c(NA, NA, NA, NA),
            Pigeon=c(NA, 3, 7, NA),
            Station_1_Pigeon=c(25, NA, NA, NA), 
            Station_2_Pigeon=c(NA, NA, 64, NA), 
            Station_3_Pigeon=c(NA, NA, NA, 50))
birds <- c("Finch", "Pigeon")

Мне нужно найти пропущенные значения для каждой птицы (в моих фактических данных их более 40) и заменить каждое пропущенное значение номером станции для этой птицы из имени столбца, а не соответствующим значением в столбце. К счастью, имена столбцов Station следуют тому же шаблону и их легко анализировать. Это мои желаемые данные:

  Finch Station_1_Finch Station_2_Finch Station_3_Finch Pigeon Station_1_Pigeon Station_2_Pigeon Station_3_Pigeon
1     1              NA              NA              NA      1               25               NA               NA
2     5              NA              NA              NA      3               NA               NA               NA
3     2              NA              60              NA      7               NA               64               NA
4     2              NA              NA              NA      3               NA               NA               50

Я думал, что mutate_at с пользовательской функцией будет самым простым способом сделать это, но я не могу заставить его работать. (Это было после попытки lapply и простой для l oop.) Вот что у меня есть:

birdcleanup <- function(b) {
  rs <- colnames(s)[grepl(pattern = deparse(names(b)[1]), colnames(s)) & 
                         grepl("^Station", colnames(s))]
  for(i in seq_along(rs)) {
    if(!is.na(s[rs[i]])) {
      v <- as.numeric(str_sub(rs[i], start = 9, end = 9))
      print(v)
    }
  }
  return(v)
}

surveytrim %>%
  mutate_at(birds, ~ if_else(is.na(.), birdcleanup(.), .))

Я подумал, что семейство функций map из purrr может помочь, но после изучения документации, виньетки и подобные вопросы здесь, я все еще в замешательстве. Что я делаю не так?

Ответы [ 2 ]

1 голос
/ 10 июля 2020

Вот с data.table

col_order <- names(s)
setDT(s)
s <- melt(s, measure.vars = birds, variable.name = "bird", variable.factor = FALSE)
s[, row_id := seq_len(.N)]
s[, value := ifelse(is.na(value), match(FALSE, is.na(mget(str_subset(names(s), bird)))), value), by = row_id]
s[, row_id := NULL]
s <- dcast(s, ... ~ bird, value.var = "value")[, .SD, .SDcols = col_order]

, но кажется, что порядок строк изменился:

   Finch Station_1_Finch Station_2_Finch Station_3_Finch Pigeon Station_1_Pigeon Station_2_Pigeon Station_3_Pigeon
1:     5              NA              NA              NA      3               NA               NA               NA
2:     2              NA              NA              NA      3               NA               NA               50
3:     1              NA              NA              NA      1               25               NA               NA
4:     2              NA              60              NA      7               NA               64               NA
1 голос
/ 10 июля 2020

Вот один из базовых R-способов решения этой проблемы:

Мы можем использовать split.default для разделения данных на основе названий птиц. Мы удаляем ненужное "Station_number" из имени столбца, чтобы оставить только имя птицы. Используя max.col, мы находим индекс первого значения в строке, отличного от NA, и заменяем NA в столбце Bird этим значением.

s[] <- do.call(cbind, lapply(split.default(s, 
              sub('Station_\\d+_', '', names(s))), function(x) {
          inds <- is.na(x[[1]])
          x[inds, 1] <- max.col(!is.na(x[inds, -1]), 'first')
          x
}))

s
#  Finch Station_1_Finch Station_2_Finch Station_3_Finch Pigeon
#1     1              NA              NA              NA      1
#2     5              NA              NA              NA      3
#3     2              NA              60              NA      7
#4     2              NA              NA              NA      3

#  Station_1_Pigeon Station_2_Pigeon Station_3_Pigeon
#1               25               NA               NA
#2               NA               NA               NA
#3               NA               64               NA
#4               NA               NA               50
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...