我无法解决这个问题。
我有一个不完整的数据集(许多行和变量(,其中有一个因素指定所有其他变量是前变量还是后变量。我需要获得所有变量的汇总统计信息,包括pre-and-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包中的现有功能来实现,但我找不到一种优雅的方法来将这些概念应用于我的问题。
如有任何帮助,我们将不胜感激。
您可以按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
有一个分组变量(group
(和时间变量(myfactor
(会有所帮助。然后,您可以使用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)))
我假设您拥有的数据集是有序的,因此每对观测都按其行索引进行分组。
默认情况下,如果mean()
函数的任何输入是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
移动到环路之外来加快速度