在 data.frame 中按组删除尾随 NA

Remove trailing NA by group in a data.frame

我有一个带有分组变量的 data.frame,值列中有一些 NA。

df = data.frame(group=c(1,1,2,2,2,2,2,3,3), value1=1:9, value2=c(NA,4,9,6,2,NA,NA,1,NA))

我可以使用 zoo::na.trim 删除列末尾的 NA:这将删除 data.frame:

的最后一行
library(zoo)
library(dplyr)
df %>% na.trim(sides="right")

现在我想按组删除尾随的NA;我如何使用 dplyr 实现此目的?

value2 列的预期输出:c(NA, 4,9,6,2,1)

使用lapply,遍历组:

do.call("rbind", lapply(split(df, df$group), na.trim, sides = "right"))

#     group value1 value2
# 1.1     1      1     NA
# 1.2     1      2      4
# 2.3     2      3      9
# 2.4     2      4      6
# 2.5     2      5      2
# 3       3      8      1

或使用by,如@Henrik所述:

do.call("rbind", by(df, df$group, na.trim, sides = "right"))

您可以编写一个小辅助函数来检查向量的尾随 NA,然后使用 group_byfilter

f <- function(x) { rev(cumsum(!is.na(rev(x)))) != 0 }

library(dplyr)
df %>% 
  group_by(group) %>% 
  filter(f(value2))
# A tibble: 6 x 3
# Groups:   group [3]
  group value1 value2
  <dbl>  <int>  <dbl>
1     1      1     NA
2     1      2      4
3     2      3      9
4     2      4      6
5     2      5      2
6     3      8      1

编辑

如果我们需要删除前导零和尾随零,我们需要稍微扩展该功能。

f1 <- function(x) { cumsum(!is.na(x)) != 0 & rev(cumsum(!is.na(rev(x)))) != 0 }

给定 df1

df1 = data.frame(group=c(1,1,2,2,2,2,2,3,3), value1=1:9, value2=c(NA,4,9,NA,2,NA,NA,1,NA))
df1
#  group value1 value2
#1     1      1     NA
#2     1      2      4
#3     2      3      9
#4     2      4     NA
#5     2      5      2
#6     2      6     NA
#7     2      7     NA
#8     3      8      1
#9     3      9     NA

我们得到这个结果

df1 %>% 
  group_by(group) %>% 
  filter(f1(value2))
# A tibble: 5 x 3
# Groups:   group [3]
  group value1 value2
  <dbl>  <int>  <dbl>
1     1      2      4
2     2      3      9
3     2      4     NA
4     2      5      2
5     3      8      1