Я хотел бы иметь возможность сохранять NA только для групп, которые имеют более двух записей, и просто хочу оставить в покое любые группы, у которых есть 1 запись (независимо от того, есть у них NA или нет). То есть, если в группе два элемента, оставьте только NA. Если он есть, просто возьмите то, что есть. Вот репрекс типа данных, которые у меня есть:
library(dplyr)
data <- data.frame(
x = c(1, NA_real_, 3, NA_real_),
y = c("grp1", "grp2", "grp2", "grp3")
)
data
#> x y
#> 1 1 grp1
#> 2 NA grp2
#> 3 3 grp2
#> 4 NA grp3
Тогда вот довольно уродливый способ, которым я добился того, что хочу:
raw <- data %>%
group_by(y) %>%
mutate(n = n())
results <- bind_rows(
raw %>%
filter(n == 2) %>%
filter(is.na(x)),
raw %>%
filter(n == 1)
) %>%
ungroup() %>%
select(-n)
results
#> # A tibble: 3 × 2
#> x y
#> <dbl> <chr>
#> 1 NA grp2
#> 2 1 grp1
#> 3 NA grp3
Обновление после уточнения: нам нужно только добавить !
и заменить ==
на >
:
library(dplyr)
data %>%
group_by(y) %>%
filter(!(!is.na(x) & n() > 1))
x y
<dbl> <chr>
1 1 grp1
2 NA grp2
3 NA grp3
Мы могли бы определить filter
с помощью max(row_number()
:
обновление: вместо max(row_number()
мы могли бы использовать n()
(большое спасибо @Juan C)
library(dplyr)
data %>%
group_by(y) %>%
filter(!(is.na(x) & n() == 1))
# filter(!(is.na(x) & max(row_number()) == 1))
x y
<dbl> <chr>
1 1 grp1
2 NA grp2
3 3 grp2
Вы могли бы упростить max(row_number()) == 1)
с помощью n() == 1
, верно?
:-) Большое спасибо, я всегда забываю об этом n().
Разве вывод здесь не отличается от ожидаемого в Q? result
из ОП сохранил x = NA для grp3?
Я смущен. Но я понял, что «сохранять NA только для групп, которые имеют более двух записей» звучит так, как будто ОП хотел удалить только NA, где в группе находится только одна запись ?! ОП должен уточнить. В любом случае ответ отличается от одного !
Я попытался уточнить вопрос. Но, как указывает @JoshWhite, это ответ, отличный от ожидаемого.
Вот еще один подход, который работает
data %>%
group_by(y) %>%
filter(!(!is.na(x) & n() > 1))
# A tibble: 3 × 2
# Groups: y [3]
x y
<dbl> <chr>
1 1 grp1
2 NA grp2
3 NA grp3
Я думаю, что это не очень большая проблема. Мы можем поменять местами `filter(!(!is.na(x) & n() > 1))` на `filter(!( is.na(x) & n() > 1))`, чтобы получить оба решения. Это все о !
.
Правда, я просто следовал ожидаемому результату ОП, а не его словам. К счастью, они получают ответ на оба вопроса!
Вы специально просили сделать это с помощью dplyr
, однако вы можете сделать это с помощью data.table
. Более интуитивно понятно:
library(data.table)
setDT(data)
data <- data[, N := .N, by = y][N <= 1 | !is.na(x)][, N := NULL]
data
Вывод:
x y
1: 1 grp1
2: 3 grp2
3: NA grp3
Если цель состоит в том, чтобы сохранить случаи NA, если группа имеет более одного наблюдения, выполните следующие действия:
data <- data[, N := .N, by = y][N <= 1 | is.na(x)][, N := NULL]
data
Вывод:
x y
1: 1 grp1
2: NA grp2
3: NA grp3
То же самое здесь. Разве вывод здесь не отличается от ожидаемого в Q? result
из ОП сохранил x = NA для grp3?
Он читал, фильтровать NA, если группа имеет более одного наблюдения. Я подумал, что это означает удаление случая NA, если группа имеет более одного NA.
"держать NA". Извините за путаницу
Не могли бы вы поделиться ожидаемым результатом? В соответствии с вашей проблемой должно быть одно наблюдение для группы 2, имеющее значение 3.