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

时间:2019-02-13 10:08:59

标签: r dataframe dplyr na zoo

我有一个带有分组变量的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)

2 个答案:

答案 0 :(得分:4)

您可以编写一个小的辅助函数,以检查向量的尾随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

答案 1 :(得分:3)

使用 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

或使用{em> by ,如@Henrik所述:

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