Reputation: 147
I have a categorical column which has around 1200 levels in a data-set of around 78000 records. I want to reduce the levels on the basis of occurrences. For eg. -:
And so on.
I don't want to group less frequently occurring levels into 'Others' as it would hide a lot of important levels.
Following is the dataframe for example.
df=data.frame(
ID = c(1:10),
Name = c("Jack", "Mike","Jack", "Mike","Jack", "Mike", "Tom", "Tom", "Smith", "Tony")
)
Here I would like to reduce the levels of column 'Name' by-:
Can anyone help me to do it in R?
Upvotes: 3
Views: 306
Reputation: 887951
We can use fcase
from the devel version of data.table
(1.12.9
), which would also do evaluation lazily
library(data.table)
setDT(df)[, NewName := fcase(.N >=3, 'A',
.N >=2 & .N < 3, 'B',
default = 'C'), Name][]
# ID Name NewName
# 1: 1 Jack A
# 2: 2 Mike A
# 3: 3 Jack A
# 4: 4 Mike A
# 5: 5 Jack A
# 6: 6 Mike A
# 7: 7 Tom B
# 8: 8 Tom B
# 9: 9 Smith C
#10: 10 Tony C
Or using base R
with findInterval
with(df, rev(LETTERS[1:3])[findInterval(table(Name)[Name], 2:3) + 1])
#[1] "A" "A" "A" "A" "A" "A" "B" "B" "C" "C"
Upvotes: 0
Reputation: 37661
A base R solution using table
NameCount = table(df$Name)[df$Name]
NewName = rep("C", length(NameCount))
NewName[NameCount >= 2] = "B"
NewName[NameCount >= 3] = "A"
NewName
[1] "A" "A" "A" "A" "A" "A" "B" "B" "C" "C"
Upvotes: 2
Reputation: 389325
We can use add_count
to count instances of Name
and then check conditions with case_when
library(dplyr)
df %>%
add_count(Name) %>%
mutate(NewName = case_when(n >= 3 ~'A',
n >= 2 & n < 3 ~'B',
TRUE ~'C')) %>%
select(-n, -Name)
# ID NewName
# <int> <chr>
# 1 1 A
# 2 2 A
# 3 3 A
# 4 4 A
# 5 5 A
# 6 6 A
# 7 7 B
# 8 8 B
# 9 9 C
#10 10 C
Upvotes: 3