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

问题描述

我不能解决这个问题。

我有一个不完整的数据集(许多行和变量),其中一个因素指定了所有其他变量是前后的。我需要获取所有前后变量的摘要统计信息,包括pre-和post-value都不为NA的行。

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

以下是我要实现的目标的简单示例:

  df = data.frame(
    id = c(1,1,2,2),myfactor = as.factor(c(1,2)),var2change = c(10,10,NA,20),var3change = c(5,15,var4change = c(NA,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软件包中的现有功能来实现,但是我找不到一种将这些概念应用于我的问题的优雅方法。

任何帮助将不胜感激。

解决方法

您可以按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
,

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

默认情况下,如果mean()函数的任何输入为NA,它将返回一个NA。因此,这是一种使用NA按组获取dplyr的好方法。

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,2),myfactor = as.factor(c(1,20),var3change = c(5,15,var4change = c(NA,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"]),df[[col]])
  df[col] = NULL
  names(df)[names(df) == "new_col"] <- col
}

如果速度是一个问题,则可以通过将group_by移到循环之外来加快速度

,

拥有分组变量(group)和时间变量(myfactor)会很有帮助。然后,您可以使用dplyr进行一些整理,以创建所需的变量。

library(dplyr)

df = data.frame(
  group = rep(c(1,each = 2),20)
)

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

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...