dplyr变更列范围的行方向最大值

beq87vna  于 2022-12-06  发布在  其他
关注(0)|答案(8)|浏览(238)

我可以使用下面的语句返回最多2列

newiris<-iris %>%
 rowwise() %>%
 mutate(mak=max(Sepal.Width,Petal.Length))

我想做的是在一系列列中找到最大值,这样就不必像这样命名每个列

newiris<-iris %>%
 rowwise() %>%
 mutate(mak=max(Sepal.Width:Petal.Length))

有什么想法吗?

nfeuvbwi

nfeuvbwi1#

可以使用pmax代替rowwise()来完成此操作

iris %>%
      mutate(mak=pmax(Sepal.Width,Petal.Length, Petal.Width))

如果我们想引用存储在vector中的列名,可以使用library(lazyeval)中的interp

library(lazyeval)
nm1 <- names(iris)[2:4]
iris %>% 
     mutate_(mak= interp(~pmax(v1), v1= as.name(nm1)))
khbbv19g

khbbv19g2#

使用rlang和quasiquote我们有另一个dplyr选项。首先,获取我们要计算并行最大值的行名称:

iris_cols <- iris %>% select(Sepal.Length:Petal.Width) %>% names()

然后,我们可以使用!!!rlang::syms来计算这些列的每一行的并行最大值:

iris %>%
  mutate(mak=pmax(!!!rlang::syms(iris_cols)))
  • rlang::syms接受字符串输入(列名),并将其转换为符号
  • !!!取消引用并拼接其参数,此处为列名

其给出:

Sepal.Length Sepal.Width Petal.Length Petal.Width    Species mak
1            5.1         3.5          1.4         0.2     setosa 5.1
2            4.9         3.0          1.4         0.2     setosa 4.9
3            4.7         3.2          1.3         0.2     setosa 4.7
4            4.6         3.1          1.5         0.2     setosa 4.6
5            5.0         3.6          1.4         0.2     setosa 5.0

h/t:https://stackoverflow.com/a/47773379/1036500

2cmtqfgy

2cmtqfgy3#

目前(dplyr 1.0.2),这是可行的:

newiris<-iris %>%
 rowwise() %>%
 mutate(mak=max(c_across(Sepal.Width:Petal.Length)))

这还允许您使用选择辅助程序(starts_with等)。

wvt8vs2t

wvt8vs2t4#

在使用dplyr时,为了选择一些列而不输入完整名称,我更喜欢subset函数中的select参数。
您可以得到如下所示的预期结果:

iris %>% subset(select = 2:4) %>% mutate(mak = do.call(pmax, (.))) %>%
  select(mak) %>% cbind(iris)
3bygqnnd

3bygqnnd5#

一种方法是将数据传输到select中,然后使用一个函数调用pmax,该函数使pmax成为行方式(这与@inscaven使用do.call的答案非常相似,不幸的是R中没有rowMaxs函数,因此我们必须使用一个函数使pmax成为行方式--下面我使用了purrr::pmap

library(dplyr)
library(purrr)

# to get the value of the max
iris$rowwisemax <- iris %>% select(Sepal.Width:Petal.Length) %>% pmap(pmax) %>% as.numeric

# to get the argmax
iris$whichrowwisemax <- iris %>% select(Sepal.Width:Petal.Length) %>% {names(.)[max.col(.)]}
zbwhf8kr

zbwhf8kr6#

看起来@akrun的答案只解决了你可以输入所有变量名的情况,不管是直接使用mutatemutate(pmax_value=pmax(var1, var2)),还是通过mutate_(interp(~pmax(v1, v2), v1=as.name(var1), v2=as.name(var2))使用mutate_interp的惰性求值。
如果您想使用冒号语法Sepal.Length:Petal.Width,或者您碰巧有一个包含列名的向量,我可以看到两种方法。
第一种方法更简洁,您整理数据,并在分组时取值中的最大值:

data(iris)
library(dplyr)
library(tidyr)

iris_id = iris %>% mutate(id=1:nrow(.))
iris_id %>%
  gather('attribute', 'value', Sepal.Length:Petal.Width) %>%
  group_by(id) %>%
  summarize(max_attribute=max(value)) %>%
  right_join(iris_id, by='id') %>%
  head(3)
## # A tibble: 3 × 7
##      id max_attribute Sepal.Length Sepal.Width Petal.Length Petal.Width Species
##   <int>         <dbl>        <dbl>       <dbl>        <dbl>       <dbl>  <fctr>
## 1     1           5.1          5.1         3.5          1.4         0.2  setosa
## 2     2           4.9          4.9         3.0          1.4         0.2  setosa
## 3     3           4.7          4.7         3.2          1.3         0.2  setosa

更难的方法是使用插值公式。如果你有一个字符矢量,其中有要最大化的变量名称,或者如果你的表太高/太宽,无法整理,这是很好的。

# Make a character vector of the names of the columns we want to take the
# maximum over
target_columns = iris %>% select(-Species) %>% names
## [1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"

# Make a vector of dummy variables that will take the place of the real
# column names inside the interpolated formula
dummy_vars = sapply(1:length(target_columns), function(i) sprintf('x%i', i))
## [1] "x1" "x2" "x3" "x4"

# Paste those variables together to make the argument of the pmax in the
# interpolated formula
dummy_vars_string = paste0(dummy_vars, collapse=',')
## [1] "x1,x2,x3,x4"

# Make a named list that maps the dummy variable names (e.g., x1) to the
# real variable names (e.g., Sepal.Length)
dummy_vars_list = lapply(target_columns, as.name) %>% setNames(dummy_vars)
## $x1
## Sepal.Length
##
## $x2
## Sepal.Width
## 
## $x3
## Petal.Length
##
## $x4
## Petal.Width

# Make a pmax formula using the dummy variables
max_formula = as.formula(paste0(c('~pmax(', dummy_vars_string, ')'), collapse=''))
## ~pmax(x1, x2, x3, x4)

# Interpolate the formula using the named variables
library(lazyeval)
iris %>%
  mutate_(max_attribute=interp(max_formula, .values=dummy_vars_list)) %>%
  head(3)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species max_attribute
## 1          5.1         3.5          1.4         0.2  setosa           5.1
## 2          4.9         3.0          1.4         0.2  setosa           4.9
## 3          4.7         3.2          1.3         0.2  setosa           4.7
dojqjjoe

dojqjjoe7#

下面是一个base-R解决方案:可以使用subset()选择列名范围。可以使用transform()apply()的组合添加行方向最大值。

newiris <- transform(iris, mak = apply(subset(iris, select=Sepal.Width:Petal.Length), 1, max))
txu3uszq

txu3uszq8#

如果要使用contains()starts_with()等选择辅助对象,我们可以使用

library(dplyr)
iris |> 
  mutate(max_value = purrr::pmap_dbl(select(iris, contains("petal")), pmax, na.rm=TRUE))

相关问题