R применить функцию к группам внутри фрейма данных, добавив результат как дополнительный столбец - PullRequest
0 голосов
/ 10 июля 2020

Вот код для моего примера набора данных.

df = data.frame("group" =c(rep(1,5),rep(1,6),rep(2,4),rep(2,3)), "time" = c(rep(NA,5),seq(1,6),rep(NA,4),seq(1,3)), "p" = seq(1,18) )

  group time  p
1      1   NA  1
2      1   NA  2
3      1   NA  3
4      1   NA  4
5      1   NA  5
6      1    1  6
7      1    2  7
8      1    3  8
9      1    4  9
10     1    5 10
11     1    6 11
12     2   NA 12
13     2   NA 13
14     2   NA 14
15     2   NA 15
16     2    1 16
17     2    2 17
18     2    3 18

Я хотел бы выяснить, как применить функцию по группе только к значениям, которые имеют время, а затем добавить результат в виде нового столбца в фрейм данных. Вот мой пример функции, которую я хотел бы применить.

pfunc <- function(p){
  p+5
}

Результат, который я надеюсь получить, будет выглядеть следующим образом.

 group time  p new_p
1      1   NA  1    NA
2      1   NA  2    NA
3      1   NA  3    NA
4      1   NA  4    NA
5      1   NA  5    NA
6      1    1  6    11
7      1    2  7    12
8      1    3  8    13
9      1    4  9    14
10     1    5 10    15
11     1    6 11    16
12     2   NA 12    NA
13     2   NA 13    NA
14     2   NA 14    NA
15     2   NA 15    NA
16     2    1 16    21
17     2    2 17    22
18     2    3 18    23

1 Ответ

2 голосов
/ 10 июля 2020

Вы можете попробовать это:

library(dplyr)
df %>% group_by(group) %>%
  mutate(pnew=ifelse(is.na(time),time,time+5))

# A tibble: 18 x 4
# Groups:   group [2]
   group  time     p  pnew
   <dbl> <int> <int> <dbl>
 1     1    NA     1    NA
 2     1    NA     2    NA
 3     1    NA     3    NA
 4     1    NA     4    NA
 5     1    NA     5    NA
 6     1     1     6     6
 7     1     2     7     7
 8     1     3     8     8
 9     1     4     9     9
10     1     5    10    10
11     1     6    11    11
12     2    NA    12    NA
13     2    NA    13    NA
14     2    NA    14    NA
15     2    NA    15    NA
16     2     1    16     6
17     2     2    17     7
18     2     3    18     8

Обновить

Вы можете использовать эту функцию:

increase <- function(data,n)
{
  data %>% group_by(group) %>%
    mutate(pnew=ifelse(is.na(time),time,time+n)) -> result
  return(result)
}

increase(df,n = 10)

# A tibble: 18 x 4
# Groups:   group [2]
   group  time     p  pnew
   <dbl> <int> <int> <dbl>
 1     1    NA     1    NA
 2     1    NA     2    NA
 3     1    NA     3    NA
 4     1    NA     4    NA
 5     1    NA     5    NA
 6     1     1     6    11
 7     1     2     7    12
 8     1     3     8    13
 9     1     4     9    14
10     1     5    10    15
11     1     6    11    16
12     2    NA    12    NA
13     2    NA    13    NA
14     2    NA    14    NA
15     2    NA    15    NA
16     2     1    16    11
17     2     2    17    12
18     2     3    18    13

Обновление 2

Надеюсь, это поможет:

df %>% group_by(group) %>% rowwise() %>% mutate(pnew=ifelse(is.na(time),NA,pfunc(time)))

# A tibble: 18 x 4
# Rowwise:  group
   group  time     p  pnew
   <dbl> <int> <int> <dbl>
 1     1    NA     1    NA
 2     1    NA     2    NA
 3     1    NA     3    NA
 4     1    NA     4    NA
 5     1    NA     5    NA
 6     1     1     6     6
 7     1     2     7     7
 8     1     3     8     8
 9     1     4     9     9
10     1     5    10    10
11     1     6    11    11
12     2    NA    12    NA
13     2    NA    13    NA
14     2    NA    14    NA
15     2    NA    15    NA
16     2     1    16     6
17     2     2    17     7
18     2     3    18     8
...