Замена значений в коэффициенте на основе частоты уровней

#r

#r

Вопрос:

Вот фрейм данных:

 vegetables <- c("carrots", "carrots", "carrots", "carrots", "carrots")
animals <- c("cats", "dogs", "dogs", "fish", "cats")
df <- data.frame(vegetables, animals)
  

Выглядит так:

 > df
  vegetables animals
1    carrots    cats
2    carrots    dogs
3    carrots    dogs
4    carrots    fish
5    carrots    cats
  

Если бы я хотел удалить строки, в которых частота уровней была ниже, например, 2 (так что ловите рыбу в примере df), затем удалите эту строку:

 for ( i in names(df) ) {
  df <- subset(df, with(df, df[,i] %in% names(which(table(df[,i]) >= 2))))
}

> df
  vegetables animals
1    carrots    cats
2    carrots    dogs
3    carrots    dogs
5    carrots    cats
  

Но что, если я не хочу удалять наблюдение, а вместо этого заменяю fish на «bla».

Как бы я это сделал?

Желаемый результат:

 > df
  vegetables animals
1    carrots    cats
2    carrots    dogs
3    carrots    dogs
4    carrots    bla
5    carrots    cats
  

Ответ №1:

Не уверен, важны ли уровни переменной, если нет, вы можете сделать следующее с stringsAsFactors=FALSE помощью опции as в data.frame

 vegetables <- c("carrots", "carrots", "carrots", "carrots", "carrots")
animals <- c("cats", "dogs", "dogs", "fish", "cats")
DF <- data.frame(vegetables, animals,stringsAsFactors=FALSE)

threshold = 2
DF$animals[ DF$animals == names(which(table(DF$animals) < threshold)) ] = "foo"

DF
#  vegetables animals
#1    carrots    cats
#2    carrots    dogs
#3    carrots    dogs
#4    carrots     foo
#5    carrots    cats
  

Комментарии:

1. Спасибо за ответ. Я пытался использовать его в моем реальном фрейме данных, но stringsAsFactors=FALSE вызывал у меня проблемы

Ответ №2:

Вы можете просто обновить уровни, используя таблицу для индексации, какие из них нужно изменить:

 levels(df$animals)[table(df$animals) < 2] <- 'bla'

df
##   vegetables animals
## 1    carrots    cats
## 2    carrots    dogs
## 3    carrots    dogs
## 4    carrots     bla
## 5    carrots    cats
  

Комментарии:

1. вау! Это тоже работает и является самым простым. С одной стороны, я хочу быть лояльным к @akrun и поддерживать его ответ, поскольку он был действительно терпелив и очень помог мне в комментариях (теперь удалены). С другой стороны, это самый простой и, по-видимому, лучший вариант

2. Это так здорово! Так элегантно!

Ответ №3:

Мы можем использовать data.table

 library(data.table)
setDT(df)[df[,  .I[.N > 1], by = .(vegetables, animals)]$V1]
  

Если мы хотим заменить низкочастотный элемент в каждом столбце на ‘bla’

 threshold <- 1
df[] <- lapply(df, as.character)
setDT(df)
for(j in seq_along(df)){
  df[, N := .N, c(names(df)[j])][N == threshold, names(df)[j] := "bla"][, N := NULL][]
  }
  

Комментарии:

1. @DougFir Вы хотите сказать, что хотите иметь «bla» во всех столбцах с меньшим количеством элементов? В этом случае «овощи» имеют только один элемент. Итак, вам может понадобиться пороговое значение