我有一个分类列,该列在大约78000条记录的数据集中具有大约1200个级别。我想根据发生次数降低水平。例如。 -:
以此类推。
我不想将发生频率较低的级别归为“其他”,因为这样会隐藏许多重要级别。
例如,下面是数据框。
df=data.frame(
ID = c(1:10),
Name = c("Jack", "Mike","Jack", "Mike","Jack", "Mike", "Tom", "Tom", "Smith", "Tony")
)
在这里,我想通过以下方式减少“名称”列的级别:
有人可以帮助我在R中做到这一点吗?
答案 0 :(得分:2)
我们可以使用add_count
来计数Name
的实例,然后使用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
答案 1 :(得分:2)
使用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"
答案 2 :(得分:0)
我们可以使用fcase
(data.table
)的开发版本中的1.12.9
,它也会懒惰地进行评估
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
或将base R
与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"