R - создание столбца символьных матриц - PullRequest
0 голосов
/ 31 мая 2018

Вот мой воспроизводимый фрейм данных:

library(tidyverse)
df <- structure(list(PN = c("41681", "16588", "34881", 
"36917", "33116", "68447"), `2017-10` = c(0L, 
0L, 0L, 0L, 0L, 0L), `2017-11` = c(0L, 1L, 0L, 0L, 0L, 0L), `2017-12` = c(0L, 
0L, 0L, 0L, 1L, 0L), `2018-01` = c(0L, 0L, 1L, 1L, 0L, 0L), `2018-02` = c(1L, 
0L, 0L, 0L, 0L, 0L), `2018-03` = c(0L, 0L, 0L, 0L, 0L, 0L), `2018-04` = c(0L, 
0L, 0L, 0L, 0L, 1L), Status = c("OK", "NOK", "OK", "NOK", "OK", 
"OK")), .Names = c("PN", "2017-10", "2017-11", "2017-12", 
"2018-01", "2018-02", "2018-03", "2018-04", "Status"), row.names = c(NA, 
-6L), class = c("tbl_df", "tbl", "data.frame"))

Короче говоря ... два шага, чтобы привести меня к выводу выше, были:

1 ранов анализе

mutate(n = parse_integer(str_replace_na(n, replacement = 0)))

2 позже в анализе

mutate(
  Status = 
    ifelse(
      (apply(.[, 2:7], 1, sum) > 0) & 
        (.[, 8] > 0), 
      "NOK", 
      "OK"
      )
)

Два добрых стэковых воина @joranи @akrun сообщил мне, что я "создал столбец символьных матриц" , и поэтому я продолжал получать "Ошибка вrange_impl (.data, dots): аргумент 1 имеет неподдерживаемую матрицу типов" ошибка.

На простом английском, что я сделал?Я из тех парней, которые еще не понимают разницу между атомным вектором и атомной частицей.Можете ли вы ответить, с чем-то ясным и кратким?

Или вы можете просто сказать мне прочитать главу XYZ в R для Data Science или что-то в этом роде.Я возьму это тоже (возможно, в комментариях).

1 Ответ

0 голосов
/ 01 июня 2018

Чтобы вести себя обычно ожидаемым образом, 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 для получения дополнительной информации.

...