给出一个数字数据框
A <- c(1.1, 3.0, 2.0, 4.0, 0.0, 1.3)
B <- c(0.2, 1.0, 2.4, 1.1, 1.3, 0.0)
C <- c(5.2, 1.3, 3.7, 1.7, 1.3, 1.0)
data <- data.frame(A, B, C) %>% as_tibble()
如何创建包含按行的最小正非零数字(如果可能,使用dplyr)的另一列以获得以下数据帧?
## A tibble: 6 x 4
# A B C posmin
# <dbl> <dbl> <dbl> <dbl>
#1 1.1 0.2 5.2 0.2
#2 3 1 1.3 1
#3 2 0 3.7 2
#4 4 1.1 1.7 1.1
#5 0 1.3 1.3 1.3
#6 1.3 0 1 1
简明扼要,几乎可以完成工作
data %>% mutate(posmin = pmin(A, B, C))
其中有两个问题:
pmin(A:Z)
pmin
计算行的最小值是否有类似pminpos
的东西,如果没有,我该如何创建它以便像上面代码中的pmin
一样调用它?以及如何在不通过逗号分隔的名称列表的情况下指定许多连续的列?
非常感谢您。
edit :我显然没有强调这一点,我在寻找非零正数,即严格大于> 0的数字。 -#5和#6行的值不为零。
答案 0 :(得分:2)
一种选择是将列名转换为符号,然后求值(!!!
)
library(dplyr)
data %>%
mutate_all(funs(replace(., .==0, NA))) %>%
transmute(posmin = pmin(!!! rlang::syms(names(.)), na.rm = TRUE)) %>%
bind_cols(data, .)
# A tibble: 6 x 4
# A B C posmin
# <dbl> <dbl> <dbl> <dbl>
#1 1.1 0.2 5.2 0.2
#2 3 1 1.3 1
#3 2 2.4 3.7 2
#4 4 1.1 1.7 1.1
#5 0 1.3 1.3 1.3
#6 1.3 0 1 1
或使用map/reduce
map(data, na_if, 0) %>%
reduce(pmin, na.rm = TRUE) %>%
bind_cols(data, posmin = .)
或者不使用任何外部程序包,我们可以在pmin
内单行调用do.call
data$posmin <- do.call(pmin, c(NA^ (data == 0) * data, na.rm = TRUE))
data$posmin
#[1] 0.2 1.0 2.0 1.1 1.3 1.0
或者基于@Moody_Mudskipper的注释,而不是将0分配给NA
,而是将其更改为更大的值(Inf
),然后使用pmin
data$posmin <- do.call(pmin, '[<-'(data, data <=0, value=Inf))
答案 1 :(得分:1)
您可以使用invoke
并使用@markus注释的na_if
data %>%
mutate(posmin = invoke(pmin, na_if(., 0), na.rm = TRUE))
# A tibble: 6 x 4
A B C posmin
<dbl> <dbl> <dbl> <dbl>
1 1.1 0.2 5.2 0.2
2 3 1 1.3 1
3 2 2.4 3.7 2
4 4 1.1 1.7 1.1
5 0 1.3 1.3 1.3
6 1.3 0 1 1
答案 2 :(得分:0)
apply
适合此处:
> data$posmin <- apply(data, 1, function(x) min(x[x>0]))
> data
# A tibble: 6 x 4
A B C posmin
<dbl> <dbl> <dbl> <dbl>
1 1.1 0.2 5.2 0.2
2 3 1 1.3 1
3 2 2.4 3.7 2
4 4 1.1 1.7 1.1
5 0 1.3 1.3 1.3
6 1.3 0 1 1
答案 3 :(得分:0)
以下是使用apply()
软件包的purrr
的整洁解决方案:
data %>% mutate(posmin = pmap(data, min))