Bart R
Bart R

Reputation: 157

OR statement in dplyr to calculate depending variable

I would like to calculate one single variable depending on a column specification.

example.df <- 
data.frame(trial.number = rep(1:10, 
each = 10), GY = sample(-200:200, 
100, replace = T), target.position 
= rep(c("up","down","up","down", 
"up"), each = 20))

test <- example.df %>% 
  group_by(trial.number) %>% 
  summarise(pxpos = 
max(GY[target.position == "up"]) | 
min(GY[target.position == "down"]))

So, if the target.position is "up", I want to know the max GY in that trial, when target.position = "down", I want the variable to take the min(GY).

This however doesn't work. I do believe that it is possible though! Thanks for help

Upvotes: 1

Views: 55

Answers (3)

akrun
akrun

Reputation: 887851

We can use case_when

example.df %>%
  group_by(trial.number) %>%
  summarise(pxpos = case_when(first(target.position) == "up" ~ max(GY), 
                   TRUE ~ min(GY)))
# A tibble: 10 x 2
#   trial.number pxpos
#            <int> <dbl>
#1            1   177
#2            2   183
#3            3  -142
#4            4  -191
#5            5   143
#6            6   158
#7            7  -162
#8            8  -200
#9            9   194
#10          10   113

Upvotes: 1

Ronak Shah
Ronak Shah

Reputation: 389235

Assuming you'll always have the same value in target.position in each trial.numer we can group_by trial.number and calculate max(GY) if the first value is "up" or else calculate min.

library(dplyr)

example.df %>%
    group_by(trial.number) %>%
    summarise(pxpos = if_else(target.position[1] == "up", max(GY), min(GY)))



#   trial.number pxpos
#          <int> <dbl>
# 1            1   177
# 2            2   183
# 3            3  -142
# 4            4  -191
# 5            5   143
# 6            6   158
# 7            7  -162
# 8            8  -200
# 9            9   194
#10           10   113

As pointed out by @Axeman, if_else is slow, we can instead replace it with simple if else

example.df %>%
   group_by(trial.number) %>%
   summarise(pxpos = if (target.position[1] == "up")  max(GY) else min(GY))

data

set.seed(123)
example.df <- data.frame(trial.number = rep(1:10, each = 10), 
             GY = sample(-200:200,100, replace = T), 
             target.position = rep(c("up","down","up","down", 
                 "up"), each = 20))

Upvotes: 3

tmfmnk
tmfmnk

Reputation: 40171

Another dplyr solution, using data provided by @Ronak Shah:

example.df %>%
  group_by(trial.number) %>%
  mutate(res = ifelse(target.position == "up", max(GY),
                      ifelse(target.position == "down", min(GY), NA))) %>%
  summarise(res = first(res))

  trial.number   res
          <int> <dbl>
 1            1  177.
 2            2  183.
 3            3 -142.
 4            4 -191.
 5            5  143.
 6            6  158.
 7            7 -162.
 8            8 -200.
 9            9  194.
10           10  113.

Upvotes: 1

Related Questions