这是我的可重现的数据框:
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告诉我,我“创建了一列字符矩阵”,这就是为什么我不断收到“排列_impl(.data,点)中的错误) :参数 1 属于不支持的矩阵类型” 错误。
用简单的英语来说,我做了什么?我是那种还不明白原子矢量和原子粒子之间区别的人。您能回答得简洁明了吗?
或者你可以告诉我阅读R for Data Science中的XYZ章节或类似内容。我也会接受(也许在评论中)。
最佳答案
为了按照通常预期的方式运行,ifelse
需要一个逻辑
向量作为第一个参数。
您在此处提供的内容是(将 .
替换为 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
表示输出值:
A vector of the same length and attributes (including dimensions and "class") as test
因此,Status
将是一个矩阵,一切最终都有意义;)。
另请参阅 ?dplyr::if_else
了解更多信息。
关于R - 创建一列字符矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50632685/