使用dplyr有条件地替换行中的值

时间:2017-01-25 09:32:20

标签: r dplyr

我有一个data.frame,其变量按组和年份编制索引,如下所示:

library(tidyverse)

set.seed(8675309)

df <- data.frame(
  year = rep(1991:2000, 10), 
  groups = rep(1:10, each = 10), 
  var1 = rnorm(100), 
  var2 = rnorm(100)
)

head(df)

  year groups       var1        var2
1 1991      1 -0.9965824  0.74453768
2 1992      1  0.7218241 -1.34662801
3 1993      1 -0.6172088  0.33014251
4 1994      1  2.0293916 -0.01272533
5 1995      1  1.0654161 -0.46367596
6 1996      1  0.9872197  0.20494209

某些特定年份缺少某些观察结果,比如1996年:

df[df$year == 1996, ]$var1 <- ifelse(df[df$year == 1996, ]$var1 > 0,
                                    NA, df[df$year == 1996, ]$var1)
## If 1996 is missing in var1, it is missing in all vars:
df$var2 <- ifelse(is.na(df$var1), NA, df$var2)

我的问题是,如何替换var1var2的值取决于它们是否已存在?这是我想要的要点:

df %>%
  group_by(groups) %>%
  mutate_all(funs(replace_1996_if_NA_with_value_from_1994))

2 个答案:

答案 0 :(得分:1)

你的问题不清楚,但如果你有一些默认值,你总是想用来替换缺失的值(例如,如果1994是你的基线),那么我建议你先生成这些默认值:

defaultValues <-
  df %>%
  filter(year == 1994) %>%
  select(groups
         , default_var1 = var1
         , default_var2 = var2)

然后,使用left_join合并组。这样,每一行现在也将具有默认值。然后,您可以使用coalesce选择第一个非NA值 - 当且仅当缺少该值时,这将是默认值。最后清除默认值。

df %>%
  left_join(defaultValues) %>%
  mutate(var1 = coalesce(var1, default_var1)
         , var2 = coalesce(var2, default_var2)) %>%
  select(-starts_with("default"))

如果您的默认值更复杂,您只需构建它们以匹配您想要的行为即可。例如,如果您希望它填写两年前的值,请使用:

complex_defaultValues <-
  df %>%
  mutate(year = year + 2) %>%
  rename(default_var1 = var1
         , default_var2 = var2)

然后,加入年份和小组,它将正确对齐(但请注意,如果两年前的值丢失,在coalesce之后仍然会丢失。所以,您可能需要帐户对于默认值中的缺失。)

最后,如果您只想向前传播最后一个非NA值(而不是尝试返回两年,或者始终使用相同的默认值),则可以使用fill中的tidyr

df %>%
  group_by(groups) %>%
  fill(var1, var2)

会自动填写(因此请确保您的数据按照您想要的方式排序)

答案 1 :(得分:0)

由于您不清楚如何更换缺失值,我会使用均值插补替换它们(取列的平均值并使用它来替换值)。

# Some of the observations are now missing
n <- 10
df[cbind(sample(1:nrow(df), n, replace=T), sample(1:ncol(df), n, replace=T))] <- NA

我们提取包含NA&#39;

的行
df[rowSums(is.na(df)) > 0,]
#    year groups        var1       var2
# 5  1995      1          NA -0.4636760
# 14 1994      2          NA  1.1556394
# 34 1994     NA  0.58852729 -0.7053416
# 37 1997      4  0.06391704         NA
# 47 1997     NA -0.87493144  1.1691501
# 50 2000      5  0.03609091         NA
# 54 1994     NA -2.13523626 -1.0991012
# 80 2000      8 -1.35752606         NA
# 84   NA      9  0.02038586 -1.6054171
# 92 1992     NA  0.59155773 -1.768570

使用dplyr&#39; s mutate_each()

代替
newDF <- mutate_each(df, funs(ifelse(is.na(.), mean(., na.rm=T), .)))

更新了专栏:

newDF[rowSums(is.na(df)) > 0,]

       year  groups        var1        var2
# 5  1995.000 1.00000  0.04923291 -0.46367596
# 14 1994.000 2.00000  0.04923291  1.15563940
# 34 1994.000 5.46875  0.58852729 -0.70534164
# 37 1997.000 4.00000  0.06391704 -0.04406217
# 47 1997.000 5.46875 -0.87493144  1.16915008
# 50 2000.000 5.00000  0.03609091 -0.04406217
# 54 1994.000 5.46875 -2.13523626 -1.09910122
# 80 2000.000 8.00000 -1.35752606 -0.04406217
# 84 1995.515 9.00000  0.02038586 -1.60541710
# 92 1992.000 5.46875  0.59155773 -1.76857084