Лучший способ объединить переменные в наборе данных панели в R?

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

Хотя вполне вероятно, что участники группы будут стабильно отвечать на заданный вопрос, может случиться так, что они изменят свое мнение или даже выйдут из группы. Другие могут войти в панель позже (в более поздней волне).

Допустим, это приводит к набору данных, который выглядит следующим образом, где var_1a и var_1b — две переменные, которые измеряют одно и то же, только в двух разных волнах:

mydata<-data.frame(
  var_1a = c(1,2,3,4,5,NA),
  var_1b = c(1,2,5,5,NA,NA)
)

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

Я делал это в R с помощью этой функции:

combo<-function(x,...){
  V<-rowMeans(x[, c(...) ], na.rm=T) * 
    ifelse(rowMeans(is.na(x[, c(...) ])) == ncol(x[, c(...) ]), NA, 1)
  ifelse(is.nan(V),NA,V)}

По какой-то причине это вводит «NaN», если все переменные последовательно NA для всех волн, следовательно, последняя строка кода в функции.

Это прекрасно работает, и я получаю то, что хотел:

> mydata$combo_var<-combo(mydata, c("var_1a","var_1b"))
> mydata

   var_1a var_1b combo_var
1       1      1       1.0
2       2      2       2.0
3       3     -3       0.0
4       4      9       6.5
5       5     NA       5.0
6      NA     NA        NA
7      NA     NA        NA
8      NA     NA        NA
9      NA     NA        NA
10     NA     NA        NA

Однако мне было интересно, есть ли лучший и простой способ сделать это. Есть ли способ сделать то же самое с помощью dplyr? Любое решение tidyverse?

См. также:  Как извлечь количество наблюдений за каждый год
Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 2
  1. Fabian Habersack

    Некоторые tidyverse варианты:

    Данные

    mydata <- data.frame(
      var_1a = c(1,2,3,4,5,NA),
      var_1b = c(1,2,5,5,NA,NA)
    )
    

    Опция 1

    library(dplyr)
    library(purrr)
    
    mydata <- mydata %>% 
      mutate(
        combo_var = pmap_dbl(select(., contains("var")), 
                         ~mean(c(...), na.rm = T))
        )
    

    Результат:

     var_1a var_1b combo_var
    1      1      1       1.0
    2      2      2       2.0
    3      3      5       4.0
    4      4      5       4.5
    5      5     NA       5.0
    6     NA     NA       NaN
    

    Вариант 2

    mydata <- mydata %>% 
      mutate(
        combo_var = rowMeans(select(., contains("var")), na.rm = T)
        )
    

    Результат:

     var_1a var_1b combo_var
    1      1      1       1.0
    2      2      2       2.0
    3      3      5       4.0
    4      4      5       4.5
    5      5     NA       5.0
    6     NA     NA       NaN
    

    Хорошо спасибо. Но знаете ли вы, почему вводится NaN, а не только НП? person Fabian Habersack; 08.08.2019

    NaN (не число) обычно происходит при выполнении вычислений, но результат не может быть представлен в числовом виде. Если бы мы установили na.rm = F, он вернул бы NA для строк 5 и 6. Поскольку мы сказали rowMeans удалить NA, у нас в основном есть результат, который невозможно вычислить, поэтому NaN. Ключевым моментом здесь является то, что значение не отсутствует, но не может быть вычислено. person Fabian Habersack; 08.08.2019

    небольшое изменение в опции pmap person Fabian Habersack; 08.08.2019

  2. Fabian Habersack

    Вы могли бы выразить это немного яснее, избегая ifelses.

    combo2 <- function(dat, sset) {
      r <- rowMeans(dat[sset], na.rm=TRUE)
      r[is.nan(r)] <- NA
      return(r)
    }
    mydata1$combo_var <- combo2(mydata1, c("var_1a", "var_1b"))
    
    #    var_1a var_1b combo_var
    # 1       1      1       1.0
    # 2       2      2       2.0
    # 3       3     -3       0.0
    # 4       4      9       6.5
    # 5       5     NA       5.0
    # 6      NA     NA        NA
    # 7      NA     NA        NA
    # 8      NA     NA        NA
    # 9      NA     NA        NA
    # 10     NA     NA        NA
    

    Данные

    mydata1 <- structure(list(var_1a = c(1L, 2L, 3L, 4L, 5L, NA, NA, NA, NA, 
    NA), var_1b = c(1L, 2L, -3L, 9L, NA, NA, NA, NA, NA, NA)), row.names = c(NA, 
    -10L), class = "data.frame")
    
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: