Question has been edited from the original

阅读了这篇有趣的discussion篇文章后,我想知道如何在专栏中使用dplyr替换NAs,例如,Lahman击球数据:

Source: local data frame [96,600 x 3]
Groups: teamID

   yearID teamID G_batting
1    2004    SFN        11
2    2006    CHN        43
3    2007    CHA         2
4    2008    BOS         5
5    2009    SEA         3
6    2010    SEA         4
7    2012    NYA        NA

以下not项工作如我所料

library(dplyr)
library(Lahman)

df <- Batting[ c("yearID", "teamID", "G_batting") ]
df <- group_by(df, teamID )
df$G_batting[is.na(df$G_batting)] <- mean(df$G_batting, na.rm = TRUE)

来源:本地数据帧[20 x 3]

   yearID teamID G_batting
1    2004    SFN  11.00000
2    2006    CHN  43.00000
3    2007    CHA   2.00000
4    2008    BOS   5.00000
5    2009    SEA   3.00000
6    2010    SEA   4.00000
7    2012    NYA  **49.07894**

> mean(Batting$G_battin, na.rm = TRUE)
[1] **49.07894**

事实上,它估算的是总体平均数,而不是群体平均数.在dplyr链中,您将如何做到这一点?使用基数R中的transform也可以计算not,因为它估算了总体平均值,而不是组平均值.此外,这种方法将数据转换为常规数据.镜框.有更好的方法吗?

df %.% 
  group_by( yearID ) %.%
  transform(G_batting = ifelse(is.na(G_batting), 
    mean(G_batting, na.rm = TRUE), 
    G_batting)
  )

编辑:将transform替换为mutate会产生以下错误

Error in mutate_impl(.data, named_dots(...), environment()) : 
  INTEGER() can only be applied to a 'integer', not a 'double'

编辑:添加为.integer似乎解决了错误,does产生了预期的结果.另见@eddi的答案.

df %.% 
  group_by( teamID ) %.%
  mutate(G_batting = ifelse(is.na(G_batting), as.integer(mean(G_batting, na.rm = TRUE)), G_batting))

Source: local data frame [96,600 x 3]
Groups: teamID

   yearID teamID G_batting
1    2004    SFN        11
2    2006    CHN        43
3    2007    CHA         2
4    2008    BOS         5
5    2009    SEA         3
6    2010    SEA         4
7    2012    NYA        47

> mean_NYA <- mean(filter(df, teamID == "NYA")$G_batting, na.rm = TRUE)
> as.integer(mean_NYA)
[1] 47

编辑:根据@Romain的评论,我从github安装了dplyr:

> head(df,10)
   yearID teamID G_batting
1    2004    SFN        11
2    2006    CHN        43
3    2007    CHA         2
4    2008    BOS         5
5    2009    SEA         3
6    2010    SEA         4
7    2012    NYA        NA
8    1954    ML1       122
9    1955    ML1       153
10   1956    ML1       153

> df %.% 
+   group_by(teamID)  %.%
+   mutate(G_batting = ifelse(is.na(G_batting), mean(G_batting, na.rm = TRUE), G_batting))
Source: local data frame [96,600 x 3]
Groups: teamID

   yearID teamID  G_batting
1    2004    SFN          0
2    2006    CHN          0
3    2007    CHA          0
4    2008    BOS          0
5    2009    SEA          0
6    2010    SEA 1074266112
7    2012    NYA   90693125
8    1954    ML1        122
9    1955    ML1        153
10   1956    ML1        153
..    ...    ...        ...

所以我没有得到错误(好),但我得到了一个(似乎)奇怪的结果.

推荐答案

您遇到的主要问题是,mean返回一个double,而G_batting列是一个整数.所以将平均值包装在as.integer中是可行的,或者你需要将整个列转换为numeric.

也就是说,这里有data.table个备选方案——我没有判断哪一个更快.

library(data.table)

# using ifelse
dt = data.table(a = 1:2, b = c(1,2,NA,NA,3,4,5,6,7,8))
dt[, b := ifelse(is.na(b), mean(b, na.rm = T), b), by = a]

# using a temporary column
dt = data.table(a = 1:2, b = c(1,2,NA,NA,3,4,5,6,7,8))
dt[, b.mean := mean(b, na.rm = T), by = a][is.na(b), b := b.mean][, b.mean := NULL]

这就是我理想中想要做的(there is an FR件):

# again, atm this is pure fantasy and will not work
dt[, b[is.na(b)] := mean(b, na.rm = T), by = a]

ifelsedplyr版是(如OP中所示):

dt %>% group_by(a) %>% mutate(b = ifelse(is.na(b), mean(b, na.rm = T), b))

我不知道如何在dplyr年的一行中实现第二个data.table想法.我也不确定如何阻止dplyr对数据进行混乱/排序(除了创建索引列).

R相关问答推荐

在 R 中系统地重命名字符串

如何在两个不同的数据帧上运行 cor.test()

如何在ggplot中将连续的x轴更改为离散的x轴?

空格后删除

更改输入值时不要清除(用户输入的)react 变量的值

当新列名作为字符向量给出时,在“data.table”中对数据进行分组的好方法

如何将 R 汇总与多个数字和基于文本的条件子集一起使用

跨不同数据集跟踪观察结果(例如 sub-reddits)

筛选包含列表中的值的行

在R中的数据框中重命名和重新编码新变量的范围

使用 Tidyverse 将数据从一列转换为多列

ggplot 适合图例大小到绘图大小

在 R 中推断顺序数据中的选择顺序

可以使 data.table 输出看起来更像 tibble 输出吗? (10 行,仅打印适合屏幕的列)

R pivot_longer 带有存根名称和最后一个下划线

使用箭头分配函数作为 R purrr map2

将数据框列表合并为一个数据框并一步汇总

如果R中的所有值都是NA,如何选择具有最大值的行

不能用 r 中的特殊字符改变字符串

根据 R 中第一个数据集的值向量化来自不同数据集的变量的新变量添加