r-根据唯一列项目的计数创建一个三级指标变量



背景

我有一个数据帧df:

df <- data.frame(ID =    c("a","a","a","b","b","b", "c","c","c","c","c","d","d","d","d"),
event = c("red",NA,"blue","white",NA,"white","orange",NA,"gray",NA,"red","black","magenta","purple","brown"),
stringsAsFactors=FALSE)
> df
ID   event
1   a     red
2   a    <NA>
3   a    blue
4   b   white
5   b    <NA>
6   b   white
7   c  orange
8   c    <NA>
9   c    gray
10  c    <NA>
11  c     red
12  d   black
13  d magenta
14  d  purple
15  d   brown

它在15行中有4个人(ID),每个人都有不同的event条目,这些条目在这个人中是唯一的:例如,ID=a有2个唯一的事件,红色和蓝色,而ID=b只有1个唯一的活动,白色,尽管有2个";白色";。

问题

我想创建一个新的列indicator,它统计每个ID中唯一的非NA事件的数量,并将它们按级别排序:

  • 0,如果该人只有一个唯一的非NAevent
  • 1用于2个唯一的非NAevent
  • 2用于3个或多个唯一的非NAevent

对于每个ID,级别指示符应该应用于indicator的每一行,包括event=NA行——例如,当event中存在非NA时,它不能仅为indicator=2。

换句话说,我正在寻找这样的东西:

# A tibble: 15 x 3
ID    event   indicator
<chr> <chr>       <int>
1 a     red             1
2 a     NA              1
3 a     blue            1
4 b     white           0
5 b     NA              0
6 b     white           0
7 c     orange          2
8 c     NA              2
9 c     gray            2
10 c     NA              2
11 c     red             2
12 d     black           2
13 d     magenta         2
14 d     purple          2
15 d     brown           2

我尝试过的

我一开始只是试图构建中间级别,看看我是否能得到ID=a等于1,但它是为ID=b这样做的:

df <- df %>% 
group_by(ID) %>%
mutate(indicator = if_else((n_distinct(event)) == 2, 1, 0)) %>%
ungroup()
# A tibble: 15 x 3
ID    event   indicator
<chr> <chr>       <dbl>
1 a     red             0
2 a     NA              0
3 a     blue            0
4 b     white           1
5 b     NA              1
6 b     white           1
7 c     orange          0
8 c     NA              0
9 c     gray            0
10 c     NA              0
11 c     red             0
12 d     black           0
13 d     magenta         0
14 d     purple          0
15 d     brown           0

为什么它认为两个";白色";是两个不同的事件吗?还是n_distinct不是我想的那样?

您可以使用:

library(dplyr)
df %>%
group_by(ID) %>%
mutate(x = pmax(pmin(n_distinct(event, na.rm = TRUE), 3) - 1, 0)) %>%
ungroup()
# A tibble: 15 × 3
ID    event       x
<chr> <chr>   <dbl>
1 a     red         1
2 a     NA          1
3 a     blue        1
4 b     white       0
5 b     NA          0
6 b     white       0
7 c     orange      2
8 c     NA          2
9 c     gray        2
10 c     NA          2
11 c     red         2
12 d     black       2
13 d     magenta     2
14 d     purple      2
15 d     brown       2

如果您确信没有任何组仅由NA组成,则可以删除pmax()。要回答您的问题,您需要告诉n_distinct()省略NA值,否则它们将被计算在内。

使用data.tablefcase:

library(data.table)
setDT(df)
df[,indicator:=fcase(sum(!is.na(unique(event)))<=1,0,sum(!is.na(unique(event)))==2,1,default=2),by=ID][]
ID   event indicator
1:  a     red         1
2:  a    <NA>         1
3:  a    blue         1
4:  b   white         0
5:  b    <NA>         0
6:  b   white         0
7:  c  orange         2
8:  c    <NA>         2
9:  c    gray         2
10:  c    <NA>         2
11:  c     red         2
12:  d   black         2
13:  d magenta         2
14:  d  purple         2
15:  d   brown         2

另一种可能的解决方案:

library(dplyr)
df %>% 
group_by(ID) %>% 
mutate(indicator = n_distinct(event, na.rm = T) %>% 
{case_when(. == 1 ~ 0, . == 2 ~ 1, . >= 3 ~ 2)}) %>% ungroup
#> # A tibble: 15 × 3
#>    ID    event   indicator
#>    <chr> <chr>       <dbl>
#>  1 a     red             1
#>  2 a     <NA>            1
#>  3 a     blue            1
#>  4 b     white           0
#>  5 b     <NA>            0
#>  6 b     white           0
#>  7 c     orange          2
#>  8 c     <NA>            2
#>  9 c     gray            2
#> 10 c     <NA>            2
#> 11 c     red             2
#> 12 d     black           2
#> 13 d     magenta         2
#> 14 d     purple          2
#> 15 d     brown           2

最新更新