根据一个因素查找具有不完整集的行,然后用 NA 替换不完整集存在的值

Find rows with incomplete set depending on a factor, then replace values that exist by NA for the incomplete set

我无法解决这个问题。

我有一个不完整的数据集(许多行和变量),其中一个因素指定所有其他变量是预先还是 post- 某物。我需要获取所有变量 pre- 和 post- 的汇总统计信息 - 仅包括 pre- 和 post- 值不为 NA 的行。

如果每个变量的集合不完整,我正在尝试找到一种用 NA 替换现有值的方法。

以下是我正在努力实现的一个简单示例:

  df = data.frame(
    id = c(1,1,2,2),
    myfactor = as.factor(c(1,2,1,2)),
    var2change = c(10,10,NA,20),
    var3change = c(5,10,15,20),
    var4change = c(NA,2,3,8)
     )

这导致:

  id myfactor var2change var3change var4change
1  1        1         10          5         NA
2  1        2         10         10          2
3  2        1         NA         15          3
4  2        2         20         20          8

我想要的输出是:

  id myfactor var2change var3change var4change
1  1        1         10          5         NA
2  1        2         10         10         NA
3  2        1         NA         15          3
4  2        2         NA         20          8

我要处理的变量不止一个,而且每个变量独立地以不同的方式不完整。我觉得这可以通过巧妙地使用 plyr / tidyr 包中的现有功能来实现,但我找不到将这些概念应用到我的问题的优雅方法。

如有任何帮助,我们将不胜感激。

我假设您拥有的数据集是有序的,因此每对观察值都按其行索引分组。

默认情况下,mean() 函数将 return 一个 NA 如果它的任何输入是 NA。因此,这是使用 dplyr.

按组获取 NA 的一种巧妙方法
library(dplyr)
df = data.frame(
  myfactor = as.factor(c(1,2,1,2)),
  var2change = c(10,10,NA,20)
)

# 1 Create ID variable to group rows in pairs
id = c()
j = 0
for (i in 1:length(df$var2change)){
  k = floor(j/2)
  id = c(id, k)
  j = j + 1
}
df$id = id

# Set all variables within group to NA if one of them is
df = df %>% 
  group_by(id) %>%
  mutate(var_changed = mean(var2change)) 

如果您的数据中有明确的 ID 变量,您可以替换此解决方案的第一部分。

编辑:对多个变量执行此操作(基于对问题的更改):

df = data.frame(
  id = c(1,1,2,2),
  myfactor = as.factor(c(1,2,1,2)),
  var2change = c(10,10,NA,20),
  var3change = c(5,10,15,20),
  var4change = c(NA,2,3,8)
)
for (col in 2:4) {
  col = paste0("var", col, "change")
  df = df %>% 
    group_by(id) %>%
    mutate(new_col = mean(get(col))) 
  df[["new_col"]] = ifelse(is.na(df["new_col"]), NA, df[[col]])
  df[col] = NULL
  names(df)[names(df) == "new_col"] <- col
}

如果速度有问题,您可以通过将 group_by 移出循环

来加快速度

拥有一个分组变量 (group) 以及您的时间变量 (myfactor) 会有所帮助。然后你可以做一些 finangling 来创建你想要的变量 dplyr.

library(dplyr)

df = data.frame(
  group = rep(c(1,2), each = 2),
  myfactor = as.factor(c(1,2,1,2)),
  var2change = c(10,10,NA,20)
)

df %>% group_by(group) %>%
  mutate(var3change = all(!is.na(var2change)),
         var4change = if_else(var3change, var2change, as.numeric(NA)))

您可以按 id 分组,如果任何值中包含 NA,则将其全部替换为 NA。要将函数应用于多个列,我们使用 across.

library(dplyr)

df %>%
  group_by(id) %>%
  mutate(across(starts_with('var'), ~if(any(is.na(.))) NA else .))
  #for dplyr < 1.0.0 we can use `mutate_at`
  #mutate_at(vars(starts_with('var')), ~if(any(is.na(.))) NA else .)

#     id myfactor var2change var3change var4change
#  <dbl> <fct>         <dbl>      <dbl>      <dbl>
#1     1 1                10          5         NA
#2     1 2                10         10         NA
#3     2 1                NA         15          3
#4     2 2                NA         20          8