wake-up-neo.com

dplyr mutiert zeilenweise den maximalen Spaltenbereich

Ich kann das Folgende verwenden, um das Maximum von 2 Spalten zurückzugeben

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

Was ich tun möchte, ist, das Maximum über eine Reihe von Spalten zu finden, sodass ich nicht jeden so benennen muss

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

Irgendwelche Ideen?

20
user2502836

Anstelle von rowwise() kann dies mit pmax erfolgen.

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

Möglicherweise können wir interp von library(lazyeval) verwenden, wenn wir auf die in einer vector gespeicherten Spaltennamen verweisen möchten.

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

Mit rlang und quasiquotation haben wir eine weitere Option von dplyr. Rufen Sie zunächst die Zeilennamen ab, für die Sie das parallele Maximum berechnen möchten:

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

Dann können wir !!! und rlang::syms verwenden, um das parallele Maximum für jede Zeile dieser Spalten zu berechnen:

iris %>%
  mutate(mak=pmax(!!!rlang::syms(iris_cols)))
  • rlang::syms nimmt eine Zeichenfolgeingabe (die Spaltennamen) in ein Symbol ein
  • !!! hebt das Anführungszeichen auf und fügt es zusammen, hier die Spaltennamen

Was gibt:

    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

9
Ben

Für die Auswahl einiger Spalten ohne die Eingabe von ganzen Namen bei der Verwendung von dplyr bevorzuge ich den select-Parameter aus der subset-Funktion.

Sie können das gewünschte Ergebnis wie folgt erhalten:

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

Es scheint, als würde die Antwort von @ akrun nur die Fälle ansprechen, in denen Sie die Namen aller Variablen eingeben können, ob mutate direkt mit mutate(pmax_value=pmax(var1, var2)) oder Lazy Evaluation mit mutate_ und interp über mutate_(interp(~pmax(v1, v2), v1=as.name(var1), v2=as.name(var2)) verwendet wird.

Ich habe zwei Möglichkeiten, dies zu tun, wenn Sie die Doppelpunkt-Syntax Sepal.Length:Petal.Width verwenden möchten oder wenn Sie einen Vektor mit den Spaltennamen haben.

Der erste ist eleganter. Sie säubern die Daten und nehmen in der Gruppierung das Maximum unter den Werten auf:

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

Der schwierigere Weg ist die Verwendung einer interpolierten Formel. Dies ist sinnvoll, wenn Sie einen Zeichenvektor mit den Namen der Variablen haben, für die das Maximum festgelegt werden soll, oder wenn die Tabelle zu groß/zu breit ist, um sie zu säubern.

# 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
0
Scott Olesen