부분 집합화된 데이터 프레임에서 사용되지 않는 요인 수준 삭제
다음을 포함하는 데이터 프레임이 있습니다.factor가 이 의 서브셋을 때 하는 것은 데이터 프레임의 서브셋입니다.subset또는 다른 인덱싱 기능이 있으면 새 데이터 프레임이 생성됩니다. 하만지그, 그.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
# all levels are still there!
levels(subdf$letters)
## [1] "a" "b" "c" "d" "e"
2에는 R 2.12가 droplevels()기능.
levels(droplevels(subdf$letters))
부분 집합을 설정한 후 변수에 인자()를 다시 적용하기만 하면 됩니다.
> 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)
이 동작을 원하지 않으면 요인을 사용하지 않고 문자 벡터를 사용합니다.저는 이것이 나중에 상황을 수습하는 것보다 더 말이 된다고 생각합니다.을 시도해 .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"
또한 다음과 같은 기능도 있습니다.dropUnusedLevelsHmisc 패키지의 함수입니다.그러나 부분 집합 연산자를 변경해야만 작동합니다.[여기에는 해당되지 않습니다.
결과적으로, 열 단위로 직접 접근하는 것은 간단합니다.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)
편집:
또한 효과가 있습니다! 지니 덕분입니다.
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"
이건 정말 불쾌합니다.다른 패키지를 로드하지 않기 위해 보통 다음과 같이 작업합니다.
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")
작동하지 않습니다.
이것은 분명히 많은 레벨이 있을 때 이상적이지 않지만, 몇몇에게는 빠르고 쉽습니다.
▁▁at▁looking다.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"
여기 그것을 하는 방법이 있습니다.
varFactor <- factor(letters[1:15])
varFactor <- varFactor[1:5]
varFactor <- varFactor[drop=T]
이를 위해 유틸리티 기능을 작성했습니다.이제 gdata의 drop.levels에 대해 알게 되었으니, 그것은 거의 비슷하게 보입니다.여기 있습니다(여기서부터).
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
}
매우 흥미로운 스레드, 저는 특히 하위 선택을 다시 요인화하는 아이디어를 좋아했습니다.저는 이전에도 비슷한 문제를 겪었고 방금 캐릭터로 전환했다가 다시 요인으로 전환했습니다.
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))
이 질문을 올려주셔서 감사합니다.하지만, 위의 해결책들 중 어느 것도 저에게 효과가 없었습니다.다른 사용자가 이 문제에 문제를 일으킬 경우를 대비하여 이 문제를 해결했습니다.
모두를 위하여factor값이 0인 수준이 들어 있는 열을 먼저 변환할 수 있습니다.character입력한 다음 다시 변환합니다.factors.
위에 게시된 질문의 경우 다음 줄의 코드를 추가하면 됩니다.
# Convert into character
subdf$letters = as.character(subdf$letters)
# Convert back into factor
subdf$letters = as.factor(subdf$letters)
# Verify the levels in the subset
levels(subdf$letters)
유감스럽게도 RevoScaleR의 rxDataStep을 사용할 때 인자()가 작동하지 않는 것 같습니다.두 단계로 나누어 수행합니다. 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()를 사용하여 문자열이 있는 콜로 변경하려고 시도했는데, 이는 잘 작동하는 것 같습니다.
성능 문제에 대해서는 확실하지 않습니다.
보다 훨씬 빠른 실제 드롭 레벨 기능droplevels그리고 어떤 종류의 불필요한 일치나 값의 표를 수행하지 않습니다.collapse::fdroplevels예:
library(collapse)
library(microbenchmark)
# wlddev data supplied in collapse, iso3c is a factor
data <- fsubset(wlddev, iso3c %!in% "USA")
microbenchmark(fdroplevels(data), droplevels(data), unit = "relative")
## Unit: relative
## expr min lq mean median uq max neval cld
## fdroplevels(data) 1.0 1.00000 1.00000 1.00000 1.00000 1.00000 100 a
## droplevels(data) 30.2 29.15873 24.54175 24.86147 22.11553 14.23274 100 b
언급URL : https://stackoverflow.com/questions/1195826/drop-unused-factor-levels-in-a-subsetted-data-frame
'programing' 카테고리의 다른 글
| git-diff에서 패치 호환 출력을 받을 수 있습니까? (0) | 2023.06.27 |
|---|---|
| 지도 보기가 화면의 일부일 때 iOS 시뮬레이터에서 어떻게 빼낼 수 있습니까? (0) | 2023.06.27 |
| Application/font-woff2가 As를 사용할 때 작동하지 않습니다.Net VNext (0) | 2023.06.27 |
| 루비에서 0 값을 매핑하고 제거하는 방법 (0) | 2023.06.27 |
| .Net 대 SSIS:SSIS는 무엇에 사용되어야 합니까? (0) | 2023.06.27 |