为组内的所有观察值创建一个新变量,该变量等于另一个变量值,条件是变量值

时间:2021-03-19 15:48:11

标签: r dplyr tidyverse data-manipulation grouped-table

我有一个如下所示的数据框:

<头>
cnpj time2 n_act_contracts
12 -1 10
12 0 8
12 1 6
13 -1 3
13 0 5
13 1 7
14 1 3
14 2 5
14 3 7
15 不适用 3
15 不适用 5
15 不适用 7

我想定义另一个变量,对于所有具有相同 cnpj 的观察,当变量 time2 等于 0 时,n_act_contracts 的值。

<头>
cnpj time2 n_act_contracts zero_n_act_contracts
12 -1 10 8
12 0 8 8
12 1 6 8
13 -1 3 5
13 0 5 5
13 1 7 5
14 1 3 不适用
14 2 5 不适用
14 3 7 不适用
15 不适用 3 不适用
15 不适用 5 不适用
15 不适用 7 不适用

我一直在使用以下几行代码来做这件事,但我需要让它更有效率。

data <- data %>%
group_by(cnpj) %>%
mutate(
zero_n_act_contracts = ifelse(time2 == 0,n_act_contracts,-1000),
zero_n_act_contracts = max(zero_n_act_contracts, na.rm = TRUE),
zero_n_act_contracts = ifelse(zero_n_act_contracts == -1000,NA,zero_n_act_contracts))

obs:我已经尝试用 dplyr: "if_else" 替换 base "ifelse",但我的代码运行时间更长。

2 个答案:

答案 0 :(得分:1)

我们可以使用

library(dplyr)
data %>% 
  group_by(cnpj) %>% 
  mutate(zero_n_act_contracts = n_act_contracts[time2 == 0][1]) %>%
  ungroup

-输出

# A tibble: 12 x 4
#    cnpj time2 n_act_contracts zero_n_act_contracts
#   <int> <int>           <int>                <int>
# 1    12    -1              10                    8
# 2    12     0               8                    8
# 3    12     1               6                    8
# 4    13    -1               3                    5
# 5    13     0               5                    5
# 6    13     1               7                    5
# 7    14     1               3                   NA
# 8    14     2               5                   NA
# 9    14     3               7                   NA
#10    15    NA               3                   NA
#11    15    NA               5                   NA
#12    15    NA               7                   NA

数据

df1 <- structure(list(cnpj = c(12L, 12L, 12L, 13L, 13L, 13L, 14L, 14L, 
14L, 15L, 15L, 15L), time2 = c(-1L, 0L, 1L, -1L, 0L, 1L, 1L, 
2L, 3L, NA, NA, NA), n_act_contracts = c(10L, 8L, 6L, 3L, 5L, 
7L, 3L, 5L, 7L, 3L, 5L, 7L)), class = "data.frame", row.names = c(NA, 
-12L))

答案 1 :(得分:1)

data.table 选项

setDT(df)[,zero_n_act_contracts := n_act_contracts[!time2],cnpj]

给予

> df
    cnpj time2 n_act_contracts zero_n_act_contracts
 1:   12    -1              10                    8
 2:   12     0               8                    8
 3:   12     1               6                    8
 4:   13    -1               3                    5
 5:   13     0               5                    5
 6:   13     1               7                    5
 7:   14     1               3                   NA
 8:   14     2               5                   NA
 9:   14     3               7                   NA
10:   15    NA               3                   NA
11:   15    NA               5                   NA
12:   15    NA               7                   NA