R의 기본 데이터 유형 중 하나는 요인입니다. 내 경험상 요인은 기본적으로 고통이며 절대 사용하지 않습니다. 나는 항상 문자로 변환합니다. 뭔가 빠진 것 같은 기분이 듭니다.
요인 데이터 유형이 필요한 경우 요인을 그룹화 변수로 사용하는 함수의 몇 가지 중요한 예가 있습니까? 요인을 사용해야하는 특정 상황이 있습니까?
R의 기본 데이터 유형 중 하나는 요인입니다. 내 경험상 요인은 기본적으로 고통이며 절대 사용하지 않습니다. 나는 항상 문자로 변환합니다. 뭔가 빠진 것 같은 기분이 듭니다.
요인 데이터 유형이 필요한 경우 요인을 그룹화 변수로 사용하는 함수의 몇 가지 중요한 예가 있습니까? 요인을 사용해야하는 특정 상황이 있습니까?
답변:
요인을 사용해야합니다. 예 그들은 통증이있을 수 있지만, 내 이론에 때문에 그들이 고통있는 이유의 90 %는 점이다 read.table
하고 read.csv
, 인수 stringsAsFactors = TRUE
기본적으로 (대부분의 사용자가이 미묘를 그리워). lme4와 같은 모델 피팅 패키지는 모델을 차등 적으로 피팅하고 사용할 대비 유형을 결정하기 위해 요소와 순서가 지정된 요소를 사용하기 때문에 유용하다고 말합니다. 그리고 그래프 패키지는 또한 그들을 그룹화하는 데 사용합니다. ggplot
대부분의 모델 피팅 함수는 문자 벡터를 요인으로 강제하므로 결과는 동일합니다. 그러나 코드에 경고가 표시됩니다.
lm(Petal.Length ~ -1 + Species, data=iris)
# Call:
# lm(formula = Petal.Length ~ -1 + Species, data = iris)
# Coefficients:
# Speciessetosa Speciesversicolor Speciesvirginica
# 1.462 4.260 5.552
iris.alt <- iris
iris.alt$Species <- as.character(iris.alt$Species)
lm(Petal.Length ~ -1 + Species, data=iris.alt)
# Call:
# lm(formula = Petal.Length ~ -1 + Species, data = iris.alt)
# Coefficients:
# Speciessetosa Speciesversicolor Speciesvirginica
# 1.462 4.260 5.552
경고 메시지 : In
model.matrix.default(mt, mf, contrasts)
:변수
Species
로 변환factor
한 가지 까다로운 것은 전체 drop=TRUE
입니다. 벡터에서는 데이터에없는 요인 수준을 제거하는 데 효과적입니다. 예를 들면 :
s <- iris$Species
s[s == 'setosa', drop=TRUE]
# [1] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [11] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [21] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [31] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [41] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# Levels: setosa
s[s == 'setosa', drop=FALSE]
# [1] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [11] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [21] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [31] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [41] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# Levels: setosa versicolor virginica
그러나 ,와 data.frame
S의 동작은 [.data.frame()
다릅니다 볼 이 이메일을 하거나 ?"[.data.frame"
. drop=TRUE
on data.frame
s를 사용하면 상상 한대로 작동하지 않습니다.
x <- subset(iris, Species == 'setosa', drop=TRUE) # susbetting with [ behaves the same way
x$Species
# [1] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [11] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [21] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [31] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [41] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# Levels: setosa versicolor virginica
운 좋게도 쉽게 요인을 제거 할 수 있습니다. droplevels()
개별 요인 또는 data.frame
(R 2.12 이후)의 모든 요인에 대해 사용되지 않은 요인 수준을 삭제하기 위해 .
x <- subset(iris, Species == 'setosa')
levels(x$Species)
# [1] "setosa" "versicolor" "virginica"
x <- droplevels(x)
levels(x$Species)
# [1] "setosa"
이것은 당신이 선택한 레벨을 ggplot
레전드에 들어 가지 못하게하는 방법 입니다.
내부적으로 factor
s는 속성 수준 문자형 벡터 ( attributes(iris$Species)
및 참조 class(attributes(iris$Species)$levels)
) 가있는 정수이며 , 이는 깨끗합니다. 레벨 이름을 변경해야한다면 (그리고 문자열을 사용하고 있었다면) 이것은 훨씬 덜 효율적인 작업 이 될 것 입니다. 특히 ggplot
전설의 경우 레벨 이름을 많이 변경합니다 . 문자 벡터로 팩터를 가짜로 만들면 하나의 요소 만 변경하고 실수로 별도의 새 레벨을 생성 할 위험이 있습니다.
stringsAsFactors
함수가 아닙니다.
정렬 된 요소는 굉장합니다. 만약 내가 오렌지를 좋아하고 사과를 싫어하지만 포도는 신경 쓰지 않는다면, 그렇게 말하기 위해 이상한 색인을 관리 할 필요가 없습니다.
d <- data.frame(x = rnorm(20), f = sample(c("apples", "oranges", "grapes"), 20, replace = TRUE, prob = c(0.5, 0.25, 0.25)))
d$f <- ordered(d$f, c("apples", "grapes", "oranges"))
d[d$f >= "grapes", ]
d$f <- ordered(d$f, c("apples", "grapes", "oranges"))
습니까? 나는 그것이 데이터 프레임에서 이것을 주문했다고 추측했을 것입니다. 그러나 그 라인을 실행하고 데이터 프레임을 인쇄 한 후에는 아무것도 변하지 않습니다. 인쇄 된 주문이 변경되지 않더라도 내부 주문 만 부과합니까?
A factor
는 다른 언어의 열거 형과 가장 유사합니다. 적절한 사용은 규정 된 값 세트 중 하나만 취할 수있는 변수에 대한 것입니다. 이러한 경우 허용되는 모든 값이 특정 데이터 집합에 존재하는 것은 아니며 "빈"수준이이를 정확하게 반영합니다.
몇 가지 예를 고려하십시오. 미국 전역에서 수집 된 일부 데이터의 경우 주를 요인으로 기록해야합니다. 이 경우 특정 주에서 수집 된 사례가 없다는 사실이 관련됩니다. 해당 상태의 데이터가있을 수 있지만 (관심의 이유가 될 수있는 이유가 무엇이든) 그렇지 않은 경우가있었습니다. 고향을 모았다면 요인이되지 않습니다. 가능한 고향의 사전 명시된 세트가 없습니다. 데이터가 전국이 아닌 3 개 도시에서 수집 된 경우 도시가 요인이 될 것입니다. 처음에 세 가지 선택이 주어졌고이 3 개 도시 중 하나에서 관련 사례 / 데이터가 발견되지 않았다면 이는 관련성이 있습니다.
factor
문자열 세트에 임의의 정렬 순서를 제공하는 방법을 제공하는 것과 같은 s의 다른 측면은 s의 유용한 2 차 특성 factor
이지만 존재 이유는 아닙니다.
통계 분석을하고 실제로 데이터를 탐색 할 때 요인은 환상적입니다. 그러나 그 전에는 데이터를 읽고, 정리하고, 문제를 해결하고, 병합하고, 일반적으로 조작 할 때 요소가 완전히 고통스러워집니다. 최근에는 지난 몇 년 동안과 같이 요소를 더 잘 처리하기 위해 많은 기능이 개선되었습니다. 예를 들어, rbind는 그들과 잘 어울립니다. 하위 집합 기능 후에 빈 수준을 남겨 두는 것이 여전히 성가신 일입니다.
#drop a whole bunch of unused levels from a whole bunch of columns that are factors using gdata
require(gdata)
drop.levels(dataframe)
요인의 수준을 다시 코딩하고 레이블을 다시 지정하는 것이 간단하며 수준을 재정렬하는 멋진 방법도 있다는 것을 알고 있습니다. 내 뇌는 그것들을 기억할 수 없으며 사용할 때마다 다시 배워야합니다. 레코딩은 현재보다 훨씬 쉬워야합니다.
R의 문자열 함수는 사용하기 매우 쉽고 논리적입니다. 그래서 조작 할 때 일반적으로 요소보다 문자를 선호합니다.
droplevels()
있습니다. 기본적으로 요인을 재정렬하지 않습니다.
얼마나 끔찍한 제목입니까!
많은 추정 함수를 사용하면 요인을 사용하여 더미 변수를 쉽게 정의 할 수 있다고 생각합니다. 그러나 나는 그것들을 사용하지 않습니다.
고유 한 관찰이 거의없는 매우 큰 문자 벡터가있을 때 사용합니다. 이는 특히 문자형 벡터의 문자열이 더 긴 경우 메모리 소비를 줄일 수 있습니다.
추신-제목에 대해 농담입니다. 나는 당신의 트윗을 보았다. ;-)
?factor
R-2.6.0 에 따르면 "정수 값은 4 바이트에 저장되는 반면 문자열에 대한 각 참조에는 4 바이트 또는 8 바이트의 포인터가 필요합니다."라고 말합니다. 문자열에 8 바이트가 필요한 경우 factor로 변환하는 공간을 절약 하시겠습니까?
N=100000
I 391.8 이하 대 391.5 이하를 얻었다. 따라서 factor는 약간의 메모리를 필요로합니다.
요인은 우수한 "고유 한"배지 엔진입니다. 나는 이것을 여러 번 심하게 재현했으며 때때로 몇 가지 주름에도 불구하고 매우 강력합니다.
library(dplyr)
d <- tibble(x = sample(letters[1:10], 20, replace = TRUE))
## normalize this table into an indexed value across two tables
id <- tibble(x_u = sort(unique(d$x))) %>% mutate(x_i = row_number())
di <- tibble(x_i = as.integer(factor(d$x)))
## reconstruct d$x when needed
d2 <- inner_join(di, id) %>% transmute(x = x_u)
identical(d, d2)
## [1] TRUE
이 작업을 수행하는 더 좋은 방법이 있다면보고 싶습니다 factor
. 이 기능에 대해 논의 할 수 없습니다 .
tapply (및 집계 )는 요인에 의존합니다. 이러한 기능의 정보 대 노력 비율은 매우 높습니다.
예를 들어, 한 줄의 코드 ( 아래의 tapply 호출 )에서 Cut 및 Color별로 다이아몬드의 평균 가격을 얻을 수 있습니다.
> data(diamonds, package="ggplot2")
> head(dm)
Carat Cut Clarity Price Color
1 0.23 Ideal SI2 326 E
2 0.21 Premium SI1 326 E
3 0.23 Good VS1 327 E
> tx = with(diamonds, tapply(X=Price, INDEX=list(Cut=Cut, Color=Color), FUN=mean))
> a = sort(1:diamonds(tx)[2], decreasing=T) # reverse columns for readability
> tx[,a]
Color
Cut J I H G F E D
Fair 4976 4685 5136 4239 3827 3682 4291
Good 4574 5079 4276 4123 3496 3424 3405
Very Good 5104 5256 4535 3873 3779 3215 3470
Premium 6295 5946 5217 4501 4325 3539 3631
Ideal 4918 4452 3889 3721 3375 2598 2629