programing

정보 손실 없이 인자를 정수\숫자로 변환하는 방법은 무엇입니까?

muds 2023. 7. 15. 10:41
반응형

정보 손실 없이 인자를 정수\숫자로 변환하는 방법은 무엇입니까?

요인을 숫자 또는 정수로 변환하면 값이 숫자가 아닌 기본 수준 코드를 얻습니다.

f <- factor(sample(runif(5), 20, replace = TRUE))
##  [1] 0.0248644019011408 0.0248644019011408 0.179684827337041 
##  [4] 0.0284090070053935 0.363644931698218  0.363644931698218 
##  [7] 0.179684827337041  0.249704354675487  0.249704354675487 
## [10] 0.0248644019011408 0.249704354675487  0.0284090070053935
## [13] 0.179684827337041  0.0248644019011408 0.179684827337041 
## [16] 0.363644931698218  0.249704354675487  0.363644931698218 
## [19] 0.179684827337041  0.0284090070053935
## 5 Levels: 0.0248644019011408 0.0284090070053935 ... 0.363644931698218

as.numeric(f)
##  [1] 1 1 3 2 5 5 3 4 4 1 4 2 3 1 3 5 4 5 3 2

as.integer(f)
##  [1] 1 1 3 2 5 5 3 4 4 1 4 2 3 1 3 5 4 5 3 2

에 의지해야 합니다.paste실제 값을 얻는 방법:

as.numeric(paste(f))
##  [1] 0.02486440 0.02486440 0.17968483 0.02840901 0.36364493 0.36364493
##  [7] 0.17968483 0.24970435 0.24970435 0.02486440 0.24970435 0.02840901
## [13] 0.17968483 0.02486440 0.17968483 0.36364493 0.24970435 0.36364493
## [19] 0.17968483 0.02840901

요인을 숫자로 변환하는 더 좋은 방법이 있습니까?

의 경고 섹션을 참조하십시오.

특히,as.numeric요인에 적용되는 것은 의미가 없으며 암묵적인 강제에 의해 발생할 수 있습니다.하는 f의 숫자 값인 대략원래숫자값으로,▁approxim로▁values▁to으값,▁numeric자,as.numeric(levels(f))[f]되며 권되며보약효간율보다 더 입니다.as.numeric(as.character(f)).

R에 관한 FAQ에도 비슷한 조언이 있습니다.


왜?as.numeric(levels(f))[f]보다 as.numeric(as.character(f))?

as.numeric(as.character(f))으로 입니다.as.numeric(levels(f)[f])그래서 당신은 숫자로 변환을 수행하고 있습니다.length(x) 위아가가 아닌 값nlevels(x)레벨이 .속도 차이는 레벨이 적은 긴 벡터에서 가장 두드러집니다.값이 대부분 고유하다면 속도에 큰 차이가 없을 것입니다.변환을 어떻게 하든 이 작업은 코드의 병목 현상이 될 가능성이 낮으므로 너무 걱정하지 마십시오.


약간의 타이밍

library(microbenchmark)
microbenchmark(
  as.numeric(levels(f))[f],
  as.numeric(levels(f)[f]),
  as.numeric(as.character(f)),
  paste0(x),
  paste(x),
  times = 1e5
)
## Unit: microseconds
##                         expr   min    lq      mean median     uq      max neval
##     as.numeric(levels(f))[f] 3.982 5.120  6.088624  5.405  5.974 1981.418 1e+05
##     as.numeric(levels(f)[f]) 5.973 7.111  8.352032  7.396  8.250 4256.380 1e+05
##  as.numeric(as.character(f)) 6.827 8.249  9.628264  8.534  9.671 1983.694 1e+05
##                    paste0(x) 7.964 9.387 11.026351  9.956 10.810 2911.257 1e+05
##                     paste(x) 7.965 9.387 11.127308  9.956 11.093 2419.458 1e+05

R에는 요인을 변환하기 위한 (문서화되지 않은) 여러 가지 편의 기능이 있습니다.

  • as.character.factor
  • as.data.frame.factor
  • as.Date.factor
  • as.list.factor
  • as.vector.factor
  • ...

하지만 짜증나게도, 요인 -> 숫자 변환을 처리할 수 있는 것이 없습니다.Joshua Ulrich의 답변의 확장으로, 저는 당신 자신의 관용적인 기능의 정의로 이 누락을 극복할 것을 제안합니다.

as.double.factor <- function(x) {as.numeric(levels(x))[x]}

스크립트 시작 부분에 저장하거나 파일에 저장할 수 있습니다.

참고: 이 답변은 숫자 값 요인을 숫자로 변환하는 것이 아니라 범주형 요인을 해당 수준 숫자로 변환하는 것입니다.


이 게시물의 모든 답변은 결과를 생성하지 못했습니다. NA가 생성되고 있습니다.

y2<-factor(c("A","B","C","D","A")); 
as.numeric(levels(y2))[y2] 
[1] NA NA NA NA NA Warning message: NAs introduced by coercion

제게 효과가 있었던 건...

as.integer(y2)
# [1] 1 2 3 4 1

은 가장쉬방법사것용다입니는하은운것다니입▁the를 사용하는 것입니다.unfactor인자 벡터 또는 데이터 프레임을 수용할 수 있는 패키지 varhandle의 함수:

unfactor(your_factor_variable)

이 예는 빠른 시작이 될 수 있습니다.

x <- rep(c("a", "b", "c"), 20)
y <- rep(c(1, 1, 0), 20)

class(x)  # -> "character"
class(y)  # -> "numeric"

x <- factor(x)
y <- factor(y)

class(x)  # -> "factor"
class(y)  # -> "factor"

library(varhandle)
x <- unfactor(x)
y <- unfactor(y)

class(x)  # -> "character"
class(y)  # -> "numeric"

데이터 프레임에서도 사용할 수 있습니다.를 들어, 를들어예,,iris데이터 집합:

sapply(iris, class)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species
   "numeric"    "numeric"    "numeric"    "numeric"     "factor"
# load the package
library("varhandle")
# pass the iris to unfactor
tmp_iris <- unfactor(iris)
# check the classes of the columns
sapply(tmp_iris, class)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species
   "numeric"    "numeric"    "numeric"    "numeric"  "character"
# check if the last column is correctly converted
tmp_iris$Species
  [1] "setosa"     "setosa"     "setosa"     "setosa"     "setosa"    
  [6] "setosa"     "setosa"     "setosa"     "setosa"     "setosa"    
 [11] "setosa"     "setosa"     "setosa"     "setosa"     "setosa"    
 [16] "setosa"     "setosa"     "setosa"     "setosa"     "setosa"    
 [21] "setosa"     "setosa"     "setosa"     "setosa"     "setosa"    
 [26] "setosa"     "setosa"     "setosa"     "setosa"     "setosa"    
 [31] "setosa"     "setosa"     "setosa"     "setosa"     "setosa"
 [36] "setosa"     "setosa"     "setosa"     "setosa"     "setosa"
 [41] "setosa"     "setosa"     "setosa"     "setosa"     "setosa"
 [46] "setosa"     "setosa"     "setosa"     "setosa"     "setosa"
 [51] "versicolor" "versicolor" "versicolor" "versicolor" "versicolor"
 [56] "versicolor" "versicolor" "versicolor" "versicolor" "versicolor"
 [61] "versicolor" "versicolor" "versicolor" "versicolor" "versicolor"
 [66] "versicolor" "versicolor" "versicolor" "versicolor" "versicolor"
 [71] "versicolor" "versicolor" "versicolor" "versicolor" "versicolor"
 [76] "versicolor" "versicolor" "versicolor" "versicolor" "versicolor"
 [81] "versicolor" "versicolor" "versicolor" "versicolor" "versicolor"
 [86] "versicolor" "versicolor" "versicolor" "versicolor" "versicolor"
 [91] "versicolor" "versicolor" "versicolor" "versicolor" "versicolor"
 [96] "versicolor" "versicolor" "versicolor" "versicolor" "versicolor"
[101] "virginica"  "virginica"  "virginica"  "virginica"  "virginica"
[106] "virginica"  "virginica"  "virginica"  "virginica"  "virginica"
[111] "virginica"  "virginica"  "virginica"  "virginica"  "virginica"
[116] "virginica"  "virginica"  "virginica"  "virginica"  "virginica"
[121] "virginica"  "virginica"  "virginica"  "virginica"  "virginica"
[126] "virginica"  "virginica"  "virginica"  "virginica"  "virginica"
[131] "virginica"  "virginica"  "virginica"  "virginica"  "virginica"
[136] "virginica"  "virginica"  "virginica"  "virginica"  "virginica"
[141] "virginica"  "virginica"  "virginica"  "virginica"  "virginica"
[146] "virginica"  "virginica"  "virginica"  "virginica"  "virginica"

요인 레이블이 원래 값과 일치하는 경우에만 가능합니다.예를 들어 설명하겠습니다.

데터가벡가정다니합고터라이▁vector다라고 가정합니다.x:

x <- c(20, 10, 30, 20, 10, 40, 10, 40)

이제 레이블이 네 개인 요인을 생성합니다.

f <- factor(x, levels = c(10, 20, 30, 40), labels = c("A", "B", "C", "D"))

1)xdouble, 유이이 다니입중형▁type▁doublef정수 형식입니다.이것은 피할 수 없는 첫 번째 정보 손실입니다.요인은 항상 정수로 저장됩니다.

> typeof(x)
[1] "double"
> typeof(f)
[1] "integer"

값 것은 합니다.f이용할 수 있는.는 것을 알 수 있습니다.f에는 정수 값 1, 2, 3, 4 및 레이블 목록("A", "B", "C", "D")과 클래스 속성 "인자"의 두 가지 속성만 포함됩니다.그 이상은 아닙니다.

> str(f)
 Factor w/ 4 levels "A","B","C","D": 2 1 3 2 1 4 1 4
> attributes(f)
$levels
[1] "A" "B" "C" "D"

$class
[1] "factor"

원래 값으로 되돌리려면 요인을 생성하는 데 사용되는 수준 값을 알아야 합니다. 이우경c(10, 20, 30, 40)원래 수준을 올바른 순서로 알면 원래 값으로 되돌릴 수 있습니다.

> orig_levels <- c(10, 20, 30, 40)
> x1 <- orig_levels[f]
> all.equal(x, x1)
[1] TRUE

또한 원래 데이터에서 가능한 모든 값에 대해 레이블이 정의된 경우에만 작동합니다.

따라서 원래 값이 필요한 경우에는 값을 유지해야 합니다.그렇지 않으면 요인으로부터만 해당 정보를 얻을 수 없을 가능성이 높습니다.

사용할 수 있습니다.hablar::convert데이터 프레임이 있는 경우.구문은 간단합니다.

샘플 df

library(hablar)
library(dplyr)

df <- dplyr::tibble(a = as.factor(c("7", "3")),
                    b = as.factor(c("1.5", "6.3")))

해결책

df %>% 
  convert(num(a, b))

제공:

# A tibble: 2 x 2
      a     b
  <dbl> <dbl>
1    7.  1.50
2    3.  6.30

또는 하나의 열을 정수로 지정하고 하나의 숫자로 지정하려면 다음을 수행합니다.

df %>% 
  convert(int(a),
          num(b))

결과:

# A tibble: 2 x 2
      a     b
  <int> <dbl>
1     7  1.50
2     3  6.30

strtoi()요인 수준이 정수이면 효과가 있습니다.

경기에 늦게, 우연히, 나는 발견했습니다.trimws()변환할 수 있습니다.factor(3:5)c("3","4","5")그럼 전화하셔도 됩니다.as.numeric()즉, 다음과 같습니다.

as.numeric(trimws(x_factor_var))

type.convert(f)수준이 완전히 숫자인 요인에 대한 또 다른 기본 옵션입니다.

성능 측면에서는 다음과 같습니다.as.numeric(as.character(f))하지만 그렇게 빠르지는 않습니다.as.numeric(levels(f))[f].

identical(type.convert(f), as.numeric(levels(f))[f])

[1] TRUE

즉, 첫 번째 인스턴스에서 벡터가 요인으로 생성된 이유가 해결되지 않은 경우(즉, 숫자로 강제할 수 없는 일부 문자가 포함되었을 가능성이 있음) 이 접근 방식은 작동하지 않고 요인을 반환합니다.

levels(f)[1] <- "some character level"
identical(type.convert(f), as.numeric(levels(f))[f])

[1] FALSE

만약 당신이 많다면.factor로 할 열numeric,

df <- rapply(df, function(x) as.numeric(levels(x))[x], "factor", how =  "replace")

이 솔루션은 다음과 같은 경우에 강력합니다.data.frames모든 요인 수준이 숫자인 경우 혼합 유형을 포함합니다.

찾았습니다as.numeric(levels(f))[f]정역 구문을 사용하여 열 이름 목록에 적용하기가 어렵습니다.먼저 문자로 변환한 다음 정수를 사용하면 패키지를 추가하지 않고도 원래 숫자 값을 얻을 수 있습니다.아마도 가장 성능이 우수한 솔루션은 아니지만, 단순하고 읽기 쉬운 솔루션을 유지할 수 있습니다.

library(tidyverse)

tbl_df <- tibble(a = as.factor(c("7", "3")),
                 b = as.factor(c("1.5", "6.3")))

cols <- c("a", "b")

tbl_df %>%
  mutate(across(all_of(cols), as.character)) %>% 
  mutate(across(all_of(cols), as.numeric))

제가 읽을 수 있는 많은 답변들 중에서 주어진 유일한 방법은 요인의 수에 따라 변수의 수를 확장하는 것이었습니다.수준이 "dog"와 "cat"인 변수 "pet"이 있으면 pet_dog 및 pet_cat이 됩니다.

이 경우 요인 변수를 숫자 변수로 변환하여 cat=1 및 dog=0과 같은 여러 수준의 변수에 적용할 수 있는 방식으로 동일한 수의 변수를 유지하고자 했습니다.

아래에서 해당 솔루션을 찾으십시오.

crime <- data.frame(city = c("SF", "SF", "NYC"),
                    year = c(1990, 2000, 1990),
                    crime = 1:3)

indx <- sapply(crime, is.factor)

crime[indx] <- lapply(crime[indx], function(x){ 
  listOri <- unique(x)
  listMod <- seq_along(listOri)
  res <- factor(x, levels=listOri)
  res <- as.numeric(res)
  return(res)
}
)

.numeric(수준(f))[f] 솔루션이 R 4.0에서 더 이상 작동하지 않는 것 같습니다.

대체 솔루션:

factor2number <- function(x){
    data.frame(levels(x), 1:length(levels(x)), row.names = 1)[x, 1]
}

factor2number(yourFactor)

언급URL : https://stackoverflow.com/questions/3418128/how-to-convert-a-factor-to-integer-numeric-without-loss-of-information

반응형