Чтобы вести себя обычно ожидаемым образом, ifelse
нужен вектор logical
в качестве первого аргумента.
Здесь вы передаете ему (замена .
на df
):
(apply(df[, 2:7], 1, sum) > 0) & (df[, 8] > 0)
# which btw we can rewrite more clearly as:
# rowSums(df[2:7]) > 0 & df[,8] >0
# 2018-04
# [1,] FALSE
# [2,] FALSE
# [3,] FALSE
# [4,] FALSE
# [5,] FALSE
# [6,] FALSE
Этого не произойдет с обычным data.frame
, поскольку df[,8]
будет преобразовано в вектор.
Считайте ?Extract
об аргументе drop
,tibbles
ведет себя немного как data.frames
с drop = FALSE
.
head(iris[,1])
# [1] 5.1 4.9 4.7 4.6 5.0 5.4
head(iris[,1,drop=FALSE])
# Sepal.Length
# 1 5.1
# 2 4.9
# 3 4.7
# 4 4.6
# 5 5.0
# 6 5.4
head(as_tibble(iris)[,1])
# # A tibble: 6 x 1
# Sepal.Length
# <dbl>
# 1 5.1
# 2 4.9
# 3 4.7
# 4 4.6
# 5 5.0
# 6 5.4
Нам не нужно вдаваться в то, как это привело к вашему неправильному результату, давайте просто сумеем исправить ввод.
Для этого вы можете использовать df[[8]]
вместо df[,8]
, это всегда будет вектор.
df %>% mutate(
Status =
ifelse(
rowSums(.[, 2:7]) > 0 & .[[8]] > 0,
"NOK",
"OK"
)
) %>% str
# Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 6 obs. of 9 variables:
# $ PN : chr "41681" "16588" "34881" "36917" ...
# $ 2017-10: int 0 0 0 0 0 0
# $ 2017-11: int 0 1 0 0 0 0
# $ 2017-12: int 0 0 0 0 1 0
# $ 2018-01: int 0 0 1 1 0 0
# $ 2018-02: int 1 0 0 0 0 0
# $ 2018-03: int 0 0 0 0 0 0
# $ 2018-04: int 0 0 0 0 0 1
# $ Status : chr "OK" "OK" "OK" "OK" ...
Теперь структура больше не проблематична.
Другой способ, который добавляет к вашему решению только один символ подчеркивания, но не научил бы нас многому :), - использовать if_else
(из пакета dplyr
) вместо ifelse
.Он выполняет магическое преобразование внутри, что вы сделали в комментариях, используя as.vector
.
Взяв ваш оригинальный код и добавив только магический _
:
df %>% mutate(
Status =
if_else(
(apply(.[, 2:7], 1, sum) > 0) &
(.[, 8] > 0),
"NOK",
"OK"
)
) %>% str
# Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 6 obs. of 9 variables:
# $ PN : chr "41681" "16588" "34881" "36917" ...
# $ 2017-10: int 0 0 0 0 0 0
# $ 2017-11: int 0 1 0 0 0 0
# $ 2017-12: int 0 0 0 0 1 0
# $ 2018-01: int 0 0 1 1 0 0
# $ 2018-02: int 1 0 0 0 0 0
# $ 2018-03: int 0 0 0 0 0 0
# $ 2018-04: int 0 0 0 0 0 1
# $ Status : chr "OK" "OK" "OK" "OK" ...
Объяснениепри ошибке
df %>% mutate(
Status =
ifelse(
(apply(.[, 2:7], 1, sum) > 0) &
(.[, 8] > 0),
"NOK",
"OK"
)
) %>% str
# Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 6 obs. of 9 variables:
# $ PN : chr "41681" "16588" "34881" "36917" ...
# $ 2017-10: int 0 0 0 0 0 0
# $ 2017-11: int 0 1 0 0 0 0
# $ 2017-12: int 0 0 0 0 1 0
# $ 2018-01: int 0 0 1 1 0 0
# $ 2018-02: int 1 0 0 0 0 0
# $ 2018-03: int 0 0 0 0 0 0
# $ 2018-04: int 0 0 0 0 0 1
# $ Status : chr [1:6, 1] "OK" "OK" "OK" "OK" ...
# ..- attr(*, "dimnames")=List of 2
# .. ..$ : NULL
# .. ..$ : chr "2018-04"
Показывает, что Status
- это символьная матрица из 6 строк и 1 столбца.arrange
это не нравится.
почему вы получили матрицу символов?
df[, 8]
- это тибль - поэтому
df[, 8] > 0
- это матрица - ; так
(apply(.[, 2:7], 1, sum) > 0) & (.[, 8] > 0)
- это матрица
?ifelse
говорит о выходном значении:
Векторта же длина и атрибуты (включая размеры и «класс»), что и у теста
Так что Status
будет матрицей, и все, наконец, имеет смысл;).
См. также ?dplyr::if_else
для получения дополнительной информации.