如何重新编码数据帧值以仅保留那些满足特定集合的值,将其他值替换为“其他” 数据解决问题的一种方法-我觉得这很烦且不够简洁

问题描述

我正在寻找一种简洁的解决方案,最好使用dplyr来清理dataframe列中的值,以便我可以保留它们,因为它们是与某个特定集合匹配的值,而其他与那些不匹配的值匹配将被重新编码为“其他”。

示例

我有一个带有动物名字的数据框。有4个合法的动物名称,但其他行包含乱码而不是名称。我想清理该列,只保留合法的动物名称zebralioncowcat

数据

library(tidyverse)
library(stringi)

real_animals_names <- sample(c("zebra","cow","lion","cat"),size = 50,replace = TRUE)
gibberish <- do.call(paste0,Map(stri_rand_strings,n = 50,length=c(5,4,1),pattern = c('[a-z]','[0-9]','[A-Z]')))

df <- tibble(animals = sample(c(animals,gibberish)))

> df

## # A tibble: 100 x 1
##    animals   
##    <chr>     
##  1 zebra     
##  2 zebra     
##  3 rbzal0677O
##  4 lion      
##  5 cat       
##  6 cfsgt0504G
##  7 cat       
##  8 jhixe2566V
##  9 lion      
## 10 zebra     
## # ... with 90 more rows

解决问题的一种方法-我觉得这很烦且不够简洁

使用 dplyr 1.0.2

df %>%
  mutate(across(animals,recode,"lion" = "lion","zebra" = "zebra","cow" = "cow","cat" = "cat",.default = "other"))

这完成了,但是这段代码将每个动物的名字重复了两次,我觉得它很笨拙。是否有更清洁的解决方案,最好使用dplyr


下面给出了建议的答案

由于我喜欢dplyr::recode的可读性,但不喜欢将每个动物的名字重复两次;并且由于以下答案利用了%in% –我可以在自己的%in%解决方案中加入recode来使其更简单/简洁吗?

解决方法

您可以照原样保留所需的动物,然后将其余的动物变成"Others"

library(dplyr)

keep_names <- c('lion','zebra','cow','cat')

df %>% mutate(animals = ifelse(animals %in% keep_names,animals,'Others'))
,

一种base解决方案:

keep_names <- c('lion','cat')

within(df,animals[!animals %in% keep_names] <- "other")

带有dplyr的{​​{1}}选项:

replace()

使用library(tidyverse) df %>% mutate(animals = replace(animals,!animals %in% keep_names,"other")) ,您可以使用命名的字符向量对recode()进行无引号拼接。

!!!

注意: df %>% mutate(animals = recode(animals,!!!set_names(keep_names),.default = "other")) 等同于set_names(keep_names)

,

我知道您最好要求使用dplyr解决方案,但是这里是data.table解决方案(请注意,我将tibble()的调用更改为data.table()):

library(stringi)
library(data.table)

real_animals_names <- sample(c("zebra","cow","lion","cat"),size = 50,replace = TRUE)
gibberish <- do.call(paste0,Map(stri_rand_strings,n = 50,length=c(5,4,1),pattern = c('[a-z]','[0-9]','[A-Z]')))

df <- data.table(animals = sample(c(real_animals_names,gibberish)))

keep_names <- c("lion","zebra","cat")
df[!animals %in% keep_names,animals := "other"]