문제

요인이 포함 된 데이터 프레임이 있습니다. 이 데이터 프레임의 서브 세트를 사용하여 subset() 또는 다른 인덱싱 기능, 새로운 데이터 프레임이 생성됩니다. 그러나 요인 변수는 새 데이터 프레임에 존재하지 않더라도 모든 원래 수준을 유지합니다.

이로 인해 Faceted Plotting 또는 Factor 레벨에 의존하는 기능을 사용하면 두통이 생깁니다.

새 데이터 프레임의 요인에서 레벨을 제거하는 가장 간결한 방법은 무엇입니까?

내 예는 다음과 같습니다.

df <- data.frame(letters=letters[1:5],
                    numbers=seq(1:5))

levels(df$letters)
## [1] "a" "b" "c" "d" "e"

subdf <- subset(df, numbers <= 3)
##   letters numbers
## 1       a       1
## 2       b       2
## 3       c       3    

## but the levels are still there!
levels(subdf$letters)
## [1] "a" "b" "c" "d" "e"
도움이 되었습니까?

해결책

하위 집합 후 다음을 변수에 다시 적용하기 만하면됩니다.

> 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)

다른 팁

R 버전 2.12 이후 a가 있습니다 droplevels() 기능.

levels(droplevels(subdf$letters))

이 동작을 원하지 않는다면 요인을 사용하지 말고 대신 문자 벡터를 사용하십시오. 나는 이것이 나중에 물건을 패치하는 것보다 더 의미가 있다고 생각합니다. 데이터를로드하기 전에 다음을 시도하십시오 read.table 또는 read.csv:

options(stringsAsFactors = FALSE)

단점은 알파벳 순서로 제한된다는 것입니다. (재주문은 음모를위한 친구입니다)

알려진 문제이며, 한 가지 가능한 치료법이 제공합니다. 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"

동일하지만 다른 방법으로 dplyr

library(dplyr)
subdf <- df %>% filter(numbers <= 3) %>% droplevels()
str(subdf)

편집하다:

또한 작동합니다! 감사합니다 Agenis

subdf <- df %>% filter(numbers <= 3) %>% droplevels
levels(subdf$letters)

완전성을 위해 지금도 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

여기에 또 다른 방법이 있습니다. 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"

보고 droplevels 행동 양식 당신이 볼 수있는 r 소스의 코드 그것은 랩 factor 기능. 즉, 기본적으로 열을 다시 재현 할 수 있습니다 factor 기능.
데이터 아래에서 모든 요인 열에서 레벨을 삭제하는 방법.

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"

이것은 독창적입니다. 이것은 다른 패키지로드를 피하기 위해 보통 내가하는 방식입니다.

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

당신을 얻는다 :

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

새로운 레벨은 이전 레벨 (Subdf $ 문자)에서 지수를 차지하는 모든 것을 대체 할 것입니다.

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

작동하지 않습니다.

이것은 당신이 많은 수준을 가질 때 이상적이지는 않지만, 몇 가지의 경우 빠르고 쉽습니다.

나는 이것을하기 위해 유틸리티 기능을 썼습니다. 이제 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
}

다음은 그렇게하는 방법입니다

varFactor <- factor(letters[1:15])
varFactor <- varFactor[1:5]
varFactor <- varFactor[drop=T]

매우 흥미로운 스레드, 나는 특히 하위 선택을 다시 고려하는 아이디어를 좋아했습니다. 나는 전에 비슷한 문제를 겪었고 단지 캐릭터로 변환 한 다음 다시 요인으로 변환했습니다.

   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))

불행히도 rxdatastep of revoscaler를 사용할 때는 accasion ()이 작동하지 않는 것 같습니다. 1) 캐릭터로 변환하고 임시 외부 데이터 프레임 (.xdf)에 보관합니다. 2) 요소로 다시 변환하고 결정적인 외부 데이터 프레임에 저장하십시오. 이렇게하면 모든 데이터를 메모리에로드하지 않고 사용하지 않은 요인 수준이 제거됩니다.

# Step 1) Converts to character, in temporary xdf file:
rxDataStep(inData = "input.xdf", outFile = "temp.xdf", transforms = list(VAR_X = as.character(VAR_X)), overwrite = T)
# Step 2) Converts back to factor:
rxDataStep(inData = "temp.xdf", outFile = "output.xdf", transforms = list(VAR_X = as.factor(VAR_X)), overwrite = T)

전부는 아니지만 대부분의 예제를 시도했지만 내 경우에는 아무도 작동하지 않는 것 같습니다. 꽤 오랫동안 고군분투 한 후 나는 사용해 보았습니다. as.character () 팩터 열에서 그것을 잘 작동하는 것처럼 보이는 문자열이있는 콜로 변경합니다.

성능 문제는 확실하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top