【问题标题】:Replace NA's in set of columns by values from another set of columns using dplyr使用 dplyr 将一组列中的 NA 替换为另一组列中的值
【发布时间】:2018-07-14 22:22:45
【问题描述】:

我发现了一些与我相关的问题,这些问题对我有所帮助,但在关键部分有所不同,所以就这样吧。

我有一个带有一些 NA 的数据框:

type <- LETTERS[1:5]
a_pc <- c(3, NA, NA , 4, 5)
b_pc <- c(NA, 2, 7, 4, 5)
a_pc_mean <- rep(mean(a_pc, na.rm = TRUE), times = 5)
b_pc_mean <- rep(mean(b_pc, na.rm = TRUE), times = 5)

df <- data.frame(type, a_pc, b_pc, a_pc_mean, b_pc_mean)

> df
  type a_pc b_pc a_pc_mean b_pc_mean
1    A    3   NA         4       4.5
2    B   NA    2         4       4.5
3    C   NA    7         4       4.5
4    D    4    4         4       4.5
5    E    5    5         4       4.5

我想将a_pc 和b_pc 列中的NA 替换为它们各自平均列中的值。我认为一个干净的方法是使用 dplyr。到目前为止我的代码是:

library(dplyr)

df2 <- df %>%
  mutate_at(.vars = vars(ends_with("_pc")),
            .funs = funs(replace(., is.na(.), ???)

我把问号放在哪里,我需要用手段引用列,但我不知道是什么。我对 dplyr 的理解是 . 引用了 vars(ends_with("_pc")) 中的列,所以我尝试将 . 和 "_mean" 粘贴在一起,但这没有用。 This 问题接近我的问题,但它要求替换为固定值,而不是花药列中的值。

我的实际数据集有两列以上我想替换 NA's ,所以我不想明确引用它们。

编辑

我上面的原始问题并没有说明我想要做什么,所以为了澄清我发布了我的数据样本:

 > crime_pop
   subregion                 iso    year assault kidnapping      pop assault_pc kidnapping_pc
   <fct>                     <chr> <dbl>   <dbl>      <dbl>    <dbl>      <dbl>         <dbl>
 1 Caribbean                 ABW    2008      NA         NA   101353 NA           NA         
 2 Southern Asia             AFG    2008      NA         NA 27294031 NA           NA         
 3 Middle Africa             AGO    2008      NA         NA 21759420 NA           NA         
 4 Southern Europe           ALB    2008     363         10  2947314  0.000123     0.00000339
 5 Southern Europe           AND    2008     105          0    83861  0.00125      0         
 6 Western Asia              ARE    2008     631        672  6894278  0.0000915    0.0000975 
 7 South America             ARG    2008  145240         NA 40382389  0.00360     NA         
 8 Western Asia              ARM    2008     201         27  2908220  0.0000691    0.00000928
 9 Caribbean                 ATG    2008      NA         NA    92478 NA           NA         
10 Australia and New Zealand AUS    2008   68019        611 21249200  0.00320      0.0000288 

我的想法是通过计算没有缺失数据的国家/地区的人均犯罪率,获取这些数据的次区域平均值并将其应用于数据缺失的国家。

计算我使用的人均犯罪率:

crime_pop <- crime_pop %>%
  mutate_at(.vars = vars(assault:kidnapping),
            .funs = funs(pc = . / pop))

可以使用@Psidom 的回答来计算子区域的平均值:

crime_pop2 <- crime_pop %>%
  group_by(year, subregion) %>%
  mutate_at(vars(ends_with("_pc")),
            funs(replace(., is.na(.), mean(., na.rm = TRUE))))

现在 assault 和 kidnapping 中的 NA 需要分别替换为 pop 和 assault_pc 和 pop 和 kidnapping_pc 的乘积,这让我回到了最初的引用问题在 mutate_at 中使用时替换函数中的其他列。也许有一种更简单的方法可以一次性完成所有这些,我愿意接受建议。谢谢!

【问题讨论】:

  • 当我有机会时会写一个完整的答案,但据我所知,你不能像那样使用mutate_at。 vars 指的是要应用函数的列,但您基本上希望对每一列应用不同的函数。我建议您查看map2 以并行映射pc 和mean 列。
  • 您的代码中可能有一个小错误:a_pc_mean &lt;- rep(mean(a, na.rm = TRUE), times = 5) 应该是 a_pc_mean &lt;- rep(mean(a_pc, na.rm = TRUE),times = 5)。 b_pc_mean 也是如此。
  • @rgt47 是的,你是对的。我更改了变量名称以更好地反映我的实际数据,但我忘记在 mean 调用中更改它们。

标签: r dplyr


【解决方案1】:

只需使用mean(., na.rm=TRUE) 作为替代:

df %>% mutate_at(vars(ends_with('_pc')), funs(replace(., is.na(.), mean(., na.rm=TRUE))))

#  type a_pc b_pc a_pc_mean b_pc_mean
#1    A    3  4.5         4       4.5
#2    B    4  2.0         4       4.5
#3    C    4  7.0         4       4.5
#4    D    4  4.0         4       4.5
#5    E    5  5.0         4       4.5

或者您可以使用 coalesce 做同样的事情,即如果来自 . 的值为 NA,则将其替换为平均值:

df %>% mutate_at(vars(ends_with('_pc')), funs(coalesce(., mean(., na.rm=TRUE))))

#  type a_pc b_pc a_pc_mean b_pc_mean
#1    A    3  4.5         4       4.5
#2    B    4  2.0         4       4.5
#3    C    4  7.0         4       4.5
#4    D    4  4.0         4       4.5
#5    E    5  5.0         4       4.5

【讨论】:

  • 这是一种更好的方式来做我想做的事。谢谢!然而,它确实产生了一个新问题,因为我需要用“_pc”列中的相应值替换另一组列(不在示例中)中的 NA。我可能应该创建一个更好的数据示例来说明我想要做什么。我将编辑我的问题以更好地解释我想要的结果。
  • @Alexander91 您应该避免编辑旧问题。而是提出一个新问题。这也将使每个问题都有一个目的,并更好地帮助以后遇到同样问题的人。
  • 好的,下次再做。我想我找到了解决问题的好方法。我应该将它添加到我的问题中吗?
【解决方案2】:

这是一个解决方案,它使用“dplyr::select”来提取命名变量并将它们从“Hmisc”包中传递给“impute”。

bar   <- df  %>% dplyr::select(ends_with('_pc')) %>% 
sapply(., Hmisc::impute,fun= mean) 
df[, colnames(bar)] <- bar
df
#  type a_pc b_pc a_pc_mean b_pc_mean
#1    A    3  4.5         4       4.5
#2    B    4  2.0         4       4.5
#3    C    4  7.0         4       4.5
#4    D    4  4.0         4       4.5
#5    E    5  5.0         4       4.5

【讨论】:

    猜你喜欢
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    相关资源
    最近更新 更多