подмножество кадра данных в r, не оставляя правильных значений [duplicate]

Я получал эту ошибку с раскадровки. Вышеупомянутое решение, похоже, не было проблемой, поэтому я в конечном итоге удалил контроллер представления и снова добавил его (и, конечно, повторно подключил segue и переназначил класс), который его исправил. Я не знаю, что это было на самом деле, но я переименовал соответствующий класс контроллера вида незадолго до этого, так что, возможно, это что-то укусило.

434
задан zx8754 27 May 2015 в 11:17
поделиться

12 ответов

Все, что вам нужно сделать, это снова применить множитель () к вашей переменной после подмножества:

> subdf$letters
[1] a b c
Levels: a b c d e
subdf$letters <- factor(subdf$letters)
> subdf$letters
[1] a b c
Levels: a b c

ИЗМЕНИТЬ

Пример примера с параметрами:

factor(ff)      # drops the levels that do not occur

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

subdf <- subset(df, numbers <= 3)
subdf[] <- lapply(subdf, function(x) if(is.factor(x)) factor(x) else x)
337
ответ дан hatmatrix 20 August 2018 в 15:41
поделиться
  • 1
    Это нормально для одноразового использования, но в data.frame с большим количеством столбцов вы можете сделать это на каждом столбце, который является фактором ..., что приводит к необходимости в такой функции, как drop.levels () из gdata. – Dirk Eddelbuettel 29 July 2009 в 15:16
  • 2
    Я вижу ... но с точки зрения пользователя быстро написать что-то вроде subdf [] & lt; - lapply (subdf, function (x) if (is.factor (x)) factor (x) else x) ... Является ли drop.levels () намного эффективнее вычислительно или лучше с большими наборами данных? (Можно было бы переписать строку выше в for-loop для огромного фрейма данных, я полагаю.) – hatmatrix 29 July 2009 в 18:09
  • 3
    Спасибо Стивен & amp; Дирк. Я даю этому один большой палец для одного из факторов, но, надеюсь, люди прочтут эти комментарии для ваших предложений по очистке всего кадра данных факторов. – medriscoll 30 July 2009 в 05:18
  • 4
    В качестве побочного эффекта функция преобразует кадр данных в список, поэтому предпочтительнее mydf <- droplevels(mydf) решение, предложенное Романом Луштриком и Томми О'Деллом ниже. – Johan 9 May 2014 в 11:41
  • 5
    Что также может быть примечательно: rlm действительно идет не так, когда ваш data.frame содержит факторы, которые содержат уровни без данных. Вы получите сообщение об ошибке: уникальные приемы не реализованы в 'rlm'. В большинстве случаев ваша матрица не является единственной, это именно эта проблема. – Matt Bannert 19 June 2014 в 15:31

Вот еще один способ, который, я считаю, эквивалентен подходу factor(..):

> df <- data.frame(let=letters[1:5], num=1:5)
> subdf <- df[df$num <= 3, ]

> subdf$let <- subdf$let[ , drop=TRUE]

> levels(subdf$let)
[1] "a" "b" "c"
10
ответ дан ars 20 August 2018 в 15:41
поделиться

Для полноты, теперь есть fct_drop в пакете forcats http://forcats.tidyverse.org/reference/fct_drop.html .

Он отличается от droplevels тем, как он имеет дело с NA:

f <- factor(c("a", "b", NA), exclude = NULL)

droplevels(f)
# [1] a    b    <NA>
# Levels: a b <NA>

forcats::fct_drop(f)
# [1] a    b    <NA>
# Levels: a b
6
ответ дан Aurèle 20 August 2018 в 15:41
поделиться

Я написал служебные функции для этого. Теперь, когда я знаю о drop.levels gdata, он выглядит довольно похожим. Здесь они (из здесь ):

present_levels <- function(x) intersect(levels(x), x)

trim_levels <- function(...) UseMethod("trim_levels")

trim_levels.factor <- function(x)  factor(x, levels=present_levels(x))

trim_levels.data.frame <- function(x) {
  for (n in names(x))
    if (is.factor(x[,n]))
      x[,n] = trim_levels(x[,n])
  x
}
5
ответ дан Brendan OConnor 20 August 2018 в 15:41
поделиться
14
ответ дан Community 20 August 2018 в 15:41
поделиться

здесь есть способ сделать это

varFactor <- factor(letters[1:15])
varFactor <- varFactor[1:5]
varFactor <- varFactor[drop=T]
6
ответ дан David Arenburg 20 August 2018 в 15:41
поделиться

Очень интересная нить, мне особенно понравилась идея просто подставить подзаголовок снова. Раньше у меня была аналогичная проблема, и я просто перешел к символу, а затем вернулся к коэффициенту.

   df <- data.frame(letters=letters[1:5],numbers=seq(1:5))
   levels(df$letters)
   ## [1] "a" "b" "c" "d" "e"
   subdf <- df[df$numbers <= 3]
   subdf$letters<-factor(as.character(subdf$letters))
4
ответ дан DfAC 20 August 2018 в 15:41
поделиться

Это известная проблема, и одно возможное решение предоставляется drop.levels() в пакете gdata , где ваш пример становится

> drop.levels(subdf)
  letters numbers
1       a       1
2       b       2
3       c       3
> levels(drop.levels(subdf)$letters)
[1] "a" "b" "c"

Существует также dropUnusedLevels в пакете Hmisc . Однако он работает только путем изменения оператора подмножества [ и здесь неприменим.

В качестве следствия прямой подход на основе столбца является простым as.factor(as.character(data)):

> levels(subdf$letters)
[1] "a" "b" "c" "d" "e"
> subdf$letters <- as.factor(as.character(subdf$letters))
> levels(subdf$letters)
[1] "a" "b" "c"
33
ответ дан Dirk Eddelbuettel 20 August 2018 в 15:41
поделиться
  • 1
    Параметр reorder функции drop.levels стоит упомянуть: если вам нужно сохранить исходный порядок ваших факторов, используйте его с FALSE значением. – daroczig 17 January 2011 в 12:31
  • 2
    Использование gdata для просто drop.levels дает «gdata: read.xls поддержку файлов« XLS »(Excel 97-2004) ENABLED. & Quot; & quot; gdata: Невозможно загрузить perl-библиотеки, требуемые read.xls () & quot; gdata: для поддержки файлов XLSX (Excel 2007+). & quot; & quot; gdata: Запустите функцию 'installXLSXsupport ()' & quot; «gdata: для автоматической загрузки и установки perl». Используйте капельки из baseR ( stackoverflow.com/a/17218028/9295807 ) – Vrokipal 20 June 2018 в 19:12
  • 3
    Вещи происходят со временем. Вы комментируете ответ, который я написал девять лет назад. Итак, давайте рассмотрим это как подсказку, как правило, предпочитаем базовые решения R, поскольку те, которые используют функциональные возможности, которые по-прежнему будут охватывать годы N . – Dirk Eddelbuettel 20 June 2018 в 19:21

Если вы не хотите этого поведения, не используйте факторы, используйте вместо него векторы символов. Я думаю, что это имеет больше смысла, чем исправление. Попробуйте выполнить следующие действия перед загрузкой данных с помощью read.table или read.csv:

options(stringsAsFactors = FALSE)

Недостатком является то, что вы ограничены алфавитным порядком. (переупорядочить ваш друг для сюжетов)

36
ответ дан hadley 20 August 2018 в 15:41
поделиться
  • 1
    Вы также можете сделать read.csv (файл = 'foo.csv', as.is = T). – andrewj 29 July 2009 в 02:37
  • 2
    это лучший ответ. Переход на это решение имеет наибольший смысл в моем случае! – TMS 22 July 2018 в 05:58

Глядя на код droplevels методов в источнике R, вы можете видеть , он обтекает функцию factor. Это означает, что вы можете в основном воссоздать столбец с функцией factor. Ниже data.table способ сбросить уровни из всех столбцов факторов.

library(data.table)
dt = data.table(letters=factor(letters[1:5]), numbers=seq(1:5))
levels(dt$letters)
#[1] "a" "b" "c" "d" "e"
subdt = dt[numbers <= 3]
levels(subdt$letters)
#[1] "a" "b" "c" "d" "e"

upd.cols = sapply(subdt, is.factor)
subdt[, names(subdt)[upd.cols] := lapply(.SD, factor), .SDcols = upd.cols]
levels(subdt$letters)
#[1] "a" "b" "c"
6
ответ дан jangorecki 20 August 2018 в 15:41
поделиться
  • 1
    Я думаю, что путь data.table будет похож на for (j in names(DT)[sapply(DT, is.factor)]) set(DT, j = j, value = factor(DT[[j]])) – David Arenburg 24 January 2016 в 14:24
  • 2
    @DavidArenburg здесь не меняется, так как мы называем [.data.table только один раз – jangorecki 30 November 2016 в 14:25

Это неприятно. Так я обычно делаю это, чтобы не загружать другие пакеты:

levels(subdf$letters)<-c("a","b","c",NA,NA)

, который получает вас:

> subdf$letters
[1] a b c
Levels: a b c

Обратите внимание, что новые уровни заменят все, что занимает их индекс в старые значения (subdf $ letters), поэтому что-то вроде:

levels(subdf$letters)<-c(NA,"a","c",NA,"b")

не будет работать.

Это, очевидно, не идеально, когда у вас много уровней, но для Несколько, это быстро и легко.

6
ответ дан Matt Parker 20 August 2018 в 15:41
поделиться

Поскольку R версии 2.12, есть функция droplevels().

levels(droplevels(subdf$letters))
454
ответ дан Roman Luštrik 20 August 2018 в 15:41
поделиться
  • 1
    Кроме того, вы можете просто прокрутить вниз немного ... – Señor O 30 January 2014 в 19:28
  • 2
    @ RomanLuštrik К сожалению, сортировка по голосам все еще делает принятый ответ №1, хотя он (сейчас) имеет меньше голосов, чем ваш :-( – tim 28 June 2015 в 19:02
  • 3
  • 4
    Я заметил, что если у меня есть уровень NA в моем факторе (подлинный уровень NA), он падает с пониженным уровнем, даже если НС присутствуют. – Meep 5 July 2016 в 00:48
Другие вопросы по тегам:

Похожие вопросы: