Anonymize less than three occurrences of a value?

Viewed 53

I want to anonymize the values of any column that has 3 occurrences or less of a value in the entire column. I need to do this for a lot of columns so I thought across would be appropriate to use.

I am unsure how to get the "count" of unique values in a scalable way. This is my attempt so far.

  library(dplyr)
anon_low_groups <- function(df, var){
    df %>% 
    add_count({{var}}) %>% 
    mutate({{var}} := ifelse(n <= 3, "*****", {{var}})) %>% 
    select(-n)
}


mtcars %>% 
  mutate(across(c(mpg), .fns = ~anon_low_groups(., .)))
#> Error: Problem with `mutate()` input `..1`.
#> ℹ `..1 = across(c(mpg), .fns = ~anon_low_groups(., .))`.
#> x no applicable method for 'group_by' applied to an object of class "c('double', 'numeric')"

Created on 2021-11-18 by the reprex package (v0.3.0)

If I do this correctly I should get output that looks like this in a way that will to scale to multiple variables:

anon_low_groups(mtcars, mpg)
#>      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> 1  *****   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#> 2  *****   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#> 3  *****   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#> 4  *****   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#> 5  *****   8 360.0 175 3.15 3.440 17.02  0  0    3    2

Created on 2021-11-18 by the reprex package (v0.3.0)

1 Answers

We can first write a function to identify all the columns we want anonymized:

anon_low_groups <- function(var,df){
  min(table(df[var])) <= 3
}

Then identify those column numbers within the data frame:

anons <- which(purrr::map_lgl(colnames(mtcars),anon_low_groups,mtcars))

And finally replace the values in the identified columns:

mtcars %>% 
  mutate(across(.cols = anons, .fns = ~rep("****",length(.))))

    mpg cyl disp   hp drat   wt qsec vs am gear carb
1  ****   6 **** **** **** **** ****  0  1    4 ****
2  ****   6 **** **** **** **** ****  0  1    4 ****
3  ****   4 **** **** **** **** ****  1  1    4 ****
4  ****   6 **** **** **** **** ****  1  0    3 ****
5  ****   8 **** **** **** **** ****  0  0    3 ****
6  ****   6 **** **** **** **** ****  1  0    3 ****
7  ****   8 **** **** **** **** ****  0  0    3 ****
8  ****   4 **** **** **** **** ****  1  0    4 ****
9  ****   4 **** **** **** **** ****  1  0    4 ****
10 ****   6 **** **** **** **** ****  1  0    4 ****
11 ****   6 **** **** **** **** ****  1  0    4 ****
12 ****   8 **** **** **** **** ****  0  0    3 ****
13 ****   8 **** **** **** **** ****  0  0    3 ****
14 ****   8 **** **** **** **** ****  0  0    3 ****
15 ****   8 **** **** **** **** ****  0  0    3 ****
16 ****   8 **** **** **** **** ****  0  0    3 ****
17 ****   8 **** **** **** **** ****  0  0    3 ****
18 ****   4 **** **** **** **** ****  1  1    4 ****
19 ****   4 **** **** **** **** ****  1  1    4 ****
20 ****   4 **** **** **** **** ****  1  1    4 ****
21 ****   4 **** **** **** **** ****  1  0    3 ****
22 ****   8 **** **** **** **** ****  0  0    3 ****
23 ****   8 **** **** **** **** ****  0  0    3 ****
24 ****   8 **** **** **** **** ****  0  0    3 ****
25 ****   8 **** **** **** **** ****  0  0    3 ****
26 ****   4 **** **** **** **** ****  1  1    4 ****
27 ****   4 **** **** **** **** ****  0  1    5 ****
28 ****   4 **** **** **** **** ****  1  1    5 ****
29 ****   8 **** **** **** **** ****  0  1    5 ****
30 ****   6 **** **** **** **** ****  0  1    5 ****
31 ****   8 **** **** **** **** ****  0  1    5 ****
32 ****   4 **** **** **** **** ****  1  1    4 ****
Related