0
votes

I'm new to R and the tidyverse and I'm trying to understand how purrr could be used to add recursively.

I have a tibble comprised of 8 rows and 4 columns. The data in the tibble represents runners at two points in the a race. The columns are as follows:

  • point - point in race (ie 1/2 way and finish)
  • position - what place the runner is in the race at that point
  • runners - runners name
  • lengthsAhead - how many length ahead a runner is ahead of the next runner

I want to calculate beaten lengths, defined as the number of lengths behind the first place runner. For example, beaten lengths would be 0 for the first place runner and would be the sum of lengthsAhead where position is less than my position for all other runners.

Question: How would I achieve this in a tidy way using purr. My goal is to have a tibble with a new column called beatenLengths with value for each point, runners and position.

My thought was to attempt something similar to this, but I was getting anywhere:

df2 = df %>% 
  group_by(position) %>% 
  mutate(bl =if_else(position==1,0,map(lengthsAhead,someFunction)))

I have attempted to use a reprex below:

library(tidyverse)
#> Warning: package 'tidyverse' was built under R version 3.5.3
#> Warning: package 'ggplot2' was built under R version 3.5.3
#> Warning: package 'tidyr' was built under R version 3.5.3
#> Warning: package 'readr' was built under R version 3.5.3
#> Warning: package 'purrr' was built under R version 3.5.3
#> Warning: package 'dplyr' was built under R version 3.5.3
#> Warning: package 'stringr' was built under R version 3.5.3
#> Warning: package 'forcats' was built under R version 3.5.3

df = tibble(point = c(1, 1,1,1,2,2,2,2),
            position=c(1,2,3,4,1,2,3,4),
            runners = c("John","Bill", "Sam", "Sally","John","Bill", "Sally", "Sam"),
            lengthsAhead = c(0.25,0.75,2.0,0,2.25,1.75,3.0,0))

df
#> # A tibble: 8 x 4
#>   point position runners lengthsAhead
#>   <dbl>    <dbl> <chr>          <dbl>
#> 1     1        1 John            0.25
#> 2     1        2 Bill            0.75
#> 3     1        3 Sam             2   
#> 4     1        4 Sally           0   
#> 5     2        1 John            2.25
#> 6     2        2 Bill            1.75
#> 7     2        3 Sally           3   
#> 8     2        4 Sam             0
2
@IceCreamToucan - Yes, that exactly what I was looking for. I guess I don't need to use purrr or custom function. Thank you. Would you like to formally answer the question? - Mutuelinvestor

2 Answers

3
votes

I think you need to group at each point instead of position. You can try to take cumsum of lengthsAhead and subtract the current lengthsAhead value to get beaten length.

library(dplyr)

df %>% 
  group_by(point) %>% 
  mutate(bl = cumsum(lengthsAhead) - lengthsAhead)

#  point position runners lengthsAhead    bl
#  <dbl>    <dbl> <chr>          <dbl> <dbl>
#1     1        1 John            0.25  0   
#2     1        2 Bill            0.75  0.25
#3     1        3 Sam             2     1   
#4     1        4 Sally           0     3   
#5     2        1 John            2.25  0   
#6     2        2 Bill            1.75  2.25
#7     2        3 Sally           3     4   
#8     2        4 Sam             0     7   
0
votes

In base R, we can do

df$bl <- with(df, ave(lengthsAhead, point, FUN = cumsum) - lengthsAhead)