R语言 长格式数据:计算第x年的NA作为其他年份的行平均值

lyr7nygr  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(161)

我有一个相当大的纵向数据集,范围从2014年到2021年。大多数变量都可以用于每年。然而,有一些变量可以用于2014年和2016年,但不适用于2015年。在这些情况下,我想计算2015年的值作为2014年和2016年的平均值。
所以数据结构看起来如下。注意,这是非常简化的,数据集有更多的变量和观察。对于每个受访者,还有其他年份的行(很明显),我没有在这里写下来
| PID|年|变量1|变量2| Var 3|
| --|--|--|--|--|
| 1 | 2014 | 10 | 2 | 2 |
| 1 | 2015 | 15 | 8 |NA|
| 1 | 2016 | 12 | 6 | 4 |
| 2 | 2014 | 11 | 7 | 5 |
| 2 | 2015 | 16 | 3 |NA|
| 2 | 2016 | 14 | 5 | 9 |
PID是标识每个受访者的ID/编号。Var 1和Var 2每年可用,Var 3仅在2014年和2015年可用
我想要的是:
| PID|年|变量1|变量2| Var 3|
| --|--|--|--|--|
| 1 | 2014 | 10 | 2 | 2 |
| 1 | 2015 | 15 | 8 | 3 |
| 1 | 2016 | 12 | 6 | 4 |
| 2 | 2014 | 11 | 7 | 5 |
| 2 | 2015 | 16 | 3 | 7 |
| 2 | 2016 | 14 | 5 | 9 |
对于Var 3,2015年的行包含2014年和2016年的平均值,而不是NA。如何实现这一点?
我的第一个想法是通过is.na()来解决2015年的缺失值,但这将解决整个数据集中的所有NA,而不仅仅是Var 2的2015年NA。我如何具体解决这些NA,以便它a)仅计算2015年的值作为Var 2的2014年和2016年的平均值,b)仅针对PID相同的那些行,让不同受访者的价值观不会混淆?

huwehgph

huwehgph1#

你问的是imputation,这里有不同的方法来替换空/null/NA值。其中一个方法涉及基于一个或多个其他非空变量的回归值。
我实际上有点自由.你说“2014年和2016年的平均值”,在这种情况下是一样的,但如果出于某种原因,你有2014年和2017年,而缺少2015 - 2016年,那么“平均值”将有偏差,2015-2016年的值相同。

下载

library(dplyr)
quux %>%
  mutate(
    across(-Year, ~ coalesce(.x, approx(Year, .x, xout = Year)$y)),
    .by = PID
  )
#   PID Year Var 1 Var 2 Var 3
# 1   1 2014    10     2     2
# 2   1 2015    15     8     3
# 3   1 2016    12     6     4
# 4   2 2014    11     7     5
# 5   2 2015    16     3     7
# 6   2 2016    14     5     9

字符串
coalesce在逻辑上与ifelse(is.na(.x), approx(..)$y, .x)相同,这意味着如果它不是NA,那么将始终使用原始值。

... across(-Year, ~ approx(Year, .x, xout = Year)$y)


(删除coalesce,总是替换所有值),这仍然会导致相同的预期结果。但由于我不知道你的数据的来龙去脉,我想我会更安全的过程。

base R

quux[,-(1:2)] <- lapply(
  quux[,-(1:2)],
  function(V) with(quux,
    ave(as.numeric(1:nrow(quux)), PID,
        FUN = function(i) ifelse(is.na(V[i]), approx(Year[i], V[i], xout=Year[i])$y, V[i]))
  )
)
quux
#   PID Year Var 1 Var 2 Var 3
# 1   1 2014    10     2     2
# 2   1 2015    15     8     3
# 3   1 2016    12     6     4
# 4   2 2014    11     7     5
# 5   2 2015    16     3     7
# 6   2 2016    14     5     9


虽然dplyr和朋友有内置的转换分组,但在base R中,我们需要使用类似ave的东西来进行非聚合的按组计算。

  • 我使用-(1:2)手动排除了我们不想估算的列;通过指定需要估算的列(如quux[,3:5] <- lapply(quux[,3:5], ...))也可以轻松完成。
  • ave一次只对一个列(向量)起作用,所以不可能在其中直接使用Year和(比如)Var 1。因此,不是告诉ave数据是Var 1,我们使用行索引作为分组变量,并在内部使用它来计算YearVar #变量的正确索引。
  • ave返回与第一个参数相同的类(不管返回的是什么),所以我们强制行索引为numeric而不是integer。不清楚您的数据是numeric还是integer,所以您可以不使用as.numeric
  • 我们 * 可以 *(没有太大的困难)创建自己的coalesce函数(类似于dplyr::coalescedata.table::fcoalesce和SQL的COALESCE函数)并替换大部分ifelse语句,但是.

数据

quux <- structure(list(PID = c(1L, 1L, 1L, 2L, 2L, 2L), Year = c(2014L, 2015L, 2016L, 2014L, 2015L, 2016L), "Var 1" = c(10L, 15L, 12L, 11L, 16L, 14L), "Var 2" = c(2L, 8L, 6L, 7L, 3L, 5L), "Var 3" = c(2L, NA, 4L, 5L, NA, 9L)), class = "data.frame", row.names = c(NA, -6L))

相关问题