在 R 的面板数据集中组合变量的更好方法?

Better way to combine variables in panel dataset in 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)
)

现在我想自动将这些变量组合成跨越两个波的一个变量。作为一个条件,如果受访者的意见从一波改变到另一波,我想取平均值。此外,即使受访者在第 2 波中退出小组,我也希望保留第 1 波的回复。

我在 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 解决方案?

您可以通过避免使用 ifelse 来更清楚地表达这一点。

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")

一些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