Удалить конечный NA по группе в data.frame - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть 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?

Ожидаемый результат для значение2 столбец: c(NA, 4,9,6,2,1)

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Вы можете написать небольшую вспомогательную функцию, которая проверяет наличие NA s вектора, а затем использовать group_by и filter.

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

edit

Если нам нужно удалить как начальный, так и конечный ноль, нам нужно немного расширить эту функцию.

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
0 голосов
/ 13 февраля 2019

Используя 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

Или используя на , как указано @ Henrik :

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