将 NA 值替换为组中的数值

Replacing NA values to numeric values in groups

我对用数据中的数值替换 NA 值有疑问。 如果组中的所有行都是 NA,则用 100 替换它们,否则 如果组中有任何数值,请将 NAs 替换为这些数值。

类似的帖子

replace NA value with the group value

不过,我更希望有直接的 dplyr 解决方案,但这两个帖子有 zoo 包的解决方案!

df = data.frame(gr=gl(3,3),id=c("NA","NA","NA",131,"NA","NA",232,232,"NA"))

> df
  gr  id
1  1  NA
2  1  NA
3  1  NA
4  2 131
5  2  NA
6  2  NA
7  3 232
8  3 232
9  3  NA

看起来很简单所以我试了一下,

library(dplyr)
df%>%
  group_by(gr)%>%
  mutate(id_new=ifelse(all(is.na(id)),100,ifelse(any(is.numeric(id)),id[which(is.numeric(id))],NA)))

# A tibble: 9 x 3
# Groups:   gr [3]
      gr     id id_new
  <fctr> <fctr>  <lgl>
1      1     NA     NA
2      1     NA     NA
3      1     NA     NA
4      2    131     NA
5      2     NA     NA
6      2     NA     NA
7      3    232     NA
8      3    232     NA
9      3     NA     NA

所有行都变成了 NA 为什么?

预期输出

      gr     id id_new
  <fctr> <fctr>  <lgl>
1      1     NA     100
2      1     NA     100
3      1     NA     100
4      2    131     131
5      2     NA     131
6      2     NA     131
7      3    232     232
8      3    232     232
9      3     NA     232

这里的问题是您的 id 列是 factor,而不是数字,因此 none 的值将 return TRUEis.numeric()。这是因为您使用 "character" NA 值构造它。使用 "numeric" NA 值构造它,如下所示:

df = data.frame(gr=gl(3,3),id=c(NA, NA,NA,131,NA,NA,232,232,NA))

df %>%
  group_by(gr) %>% mutate(id_new=ifelse(all(is.na(id)),100,ifelse(any(is.numeric(id)),id[which(is.numeric(id))],NA)))
# A tibble: 9 x 3
# Groups:   gr [3]
  gr       id id_new
  <fct> <dbl>  <dbl>
1 1        NA    100
2 1        NA    100
3 1        NA    100
4 2       131    131
5 2        NA    131
6 2        NA    131
7 3       232    232
8 3       232    232
9 3        NA    232

您无需执行任何特殊操作即可使 NA 值变为 "numeric"c() 将在您使用 "numeric" 值传递它们时从 "logical" 强制它们。之前,由于 "character" 具有更高的优先级,c() 在包含 "NA" 而不是 NAdata.frame() 时将该列强制为 "character"由于默认 stringsAsFactors = TRUE

,因此将其转换为 "factor"

只需将 id 转换为 numeric。此外,对于 ifelese 的 else 条件,我使用了 max 以防值不唯一。将其更改为适合您的任何内容。我认为不需要复杂的 else 语句。

df%>%
  group_by(gr)%>%
  mutate(id = as.numeric(id)) %>%
  mutate(id_new=ifelse(all(is.na(id)),100,max(id, na.rm = TRUE)))