데이터 프레임에있는 여러 열의 계수에서 숫자로 클래스 변경


82

많은 수의 열을 요인에서 숫자로 변경하는 가장 빠르고 / 좋은 방법은 무엇입니까?

다음 코드를 사용했지만 내 데이터를 다시 정렬 한 것 같습니다.

> head(stats[,1:2])
  rk                 team
1  1 Washington Capitals*
2  2     San Jose Sharks*
3  3  Chicago Blackhawks*
4  4     Phoenix Coyotes*
5  5   New Jersey Devils*
6  6   Vancouver Canucks*

for(i in c(1,3:ncol(stats))) {
    stats[,i] <- as.numeric(stats[,i])
}

> head(stats[,1:2])
  rk                 team
1  2 Washington Capitals*
2 13     San Jose Sharks*
3 24  Chicago Blackhawks*
4 26     Phoenix Coyotes*
5 27   New Jersey Devils*
6 28   Vancouver Canucks*

다음과 같이 모든 열의 이름을 지정하지 않는 가장 좋은 방법은 무엇입니까?

df$colname <- as.numeric(ds$colname)

4
일반적인 솔루션이 없습니까?. 여기에 제안 된 솔루션 중 일부는 요인으로 만 작동하고 다른 일부는 항상 요인을 제외하고 작동합니다.
skan

답변:


56

Ramnath의 대답에 더하여, 경험하는 행동 은 R 수준에서 as.numeric(x)요인의 내부 숫자 표현 을 반환하기 때문 x입니다. (내부 표현이 아닌) 요인의 수준 인 숫자를 보존하려면 as.character()Ramnath의 예에 따라 먼저 문자를 통해 변환해야합니다 .

귀하의 for루프는 단지 합리적인 같다 apply호출하고 코드의 의도가 무엇인지에 관해서는 약간 더 읽을 수 있습니다. 이 줄을 변경하십시오.

stats[,i] <- as.numeric(stats[,i])

읽다

stats[,i] <- as.numeric(as.character(stats[,i]))

이다 질문 7.10 는 R 자주 묻는 질문한다.

HTH


2
어떤 종류의 루프도 필요하지 않습니다. 인덱스와 unlist ()를 사용하십시오. 편집 : 나는 이것을 설명하는 답변을 추가했습니다.
Joris Meys

이 접근 방식은이 특정 경우에만 작동합니다. 나는 그것을 사용하여 열을 변환하려고 시도했지만 factor작동하지 않았습니다. sapply또는 mutate_if더 일반적으로 적용 가능한 솔루션 인 것 같습니다.
Leo

@Leo Care를 확장하려면 이것이 작동한다는 사실을 알고 있기 때문입니다. 그건 정확히 Ramnath 그가 사용하는 것을 제외하고 아래의 같은 솔루션 apply루프를 실행하고 영업 이익이 사용 된 for명시 적으로 루프를. 사실, 투표율이 높은 모든 답변은 as.numeric(as.character())관용구를 사용합니다 .
Gavin Simpson

예, 여러 열의 클래스를로 변경하는 데 작동 numeric하지만 역으로 작동하지 않습니다 (여러 열의 클래스를로 변경 factor). 필요한 인덱스를 사용 unlist()하고 문자가있는 열에 적용될 때 모든 단일 문자를 나열 해제하므로 출력을 다시 stats[,i]. 여기에서 답을 확인하세요. stackoverflow.com/questions/45713473/…
Leo

@ 레오 물론 역으로 작동하지 않습니다! 도대체 무슨 인상을 주었습니까? 그것은 결코 설계되지 않았고 OP는 그것을 요구하지 않았습니다. 묻지 않은 질문에 대답하기가 어렵습니다. 여기 대신 요소 사용 으로 변환 하려면 잘 작동합니다. 물론, 열이 혼합되어있는 경우 선택적 으로 선택해야 하지만 그것도 사소합니다. as.factor()as.numeric(as.character())i
Gavin Simpson

73

요인을 숫자로 변경할 때는주의해야합니다. 다음은 요소에서 숫자로 열 집합을 변경하는 코드 줄입니다. 여기서는 숫자로 변경할 열이 각각 1, 3, 4 및 5라고 가정합니다. 그에 따라 변경할 수 있습니다.

cols = c(1, 3, 4, 5);    
df[,cols] = apply(df[,cols], 2, function(x) as.numeric(as.character(x)));

3
제대로 작동하지 않습니다. 예 : x<-as.factor(1:3); df<-data.frame(a=x,y=runif(3),b=x,c=x,d=x). 나는 그것이 apply이런 종류의 문제에 적절 하다고 생각하지 않습니다 .
Marek

1
적용은 이러한 상황에서 완벽하게 작동합니다. 내 코드의 오류는 함수가 열 단위로 적용되어야하므로 2 대신 margin = 1을 사용했습니다. 그에 따라 내 대답을 편집했습니다.
Ramnath

이제 작동합니다. 하지만 apply. 내 편집을 확인하십시오.
Marek

2
... 또는 Joris가 unlist. 그리고 as.character솔루션의 전환이 원인 필요하지 않은 apply변환을 df[,cols]하기 character때문에 apply(df[,cols], 2, function(x) as.numeric(x))너무 작동합니다.
Marek

@Ramnath , 당신은 =왜 사용 합니까 <-?
kittygirl 19.04.16

40

이 작업은 한 줄로 수행 할 수 있으며 for 루프 든 적용이든 루프가 필요하지 않습니다. 대신 unlist () 사용 :

# testdata
Df <- data.frame(
  x = as.factor(sample(1:5,30,r=TRUE)),
  y = as.factor(sample(1:5,30,r=TRUE)),
  z = as.factor(sample(1:5,30,r=TRUE)),
  w = as.factor(sample(1:5,30,r=TRUE))
)
##

Df[,c("y","w")] <- as.numeric(as.character(unlist(Df[,c("y","w")])))

str(Df)

편집 : 코드의 경우 다음과 같습니다.

id <- c(1,3:ncol(stats))) 
stats[,id] <- as.numeric(as.character(unlist(stats[,id])))

당연히 1 열 데이터 프레임이 있고 R의 자동 차원 축소를 벡터로 변환하지 않으려면 drop=FALSE인수 를 추가해야합니다 .


1
작은 개선 은 둘 다의 설정 recursiveuse.names매개 변수 일 수 있습니다 . unlistFALSE
Marek

@Marek : 사실입니다. 나는이 게임 :-) 사랑
요리스 MEYS

나는 미래에 답을 찾는 사람들을 위해 추가 할 것입니다. 이것은 데이터 프레임이 단 하나의 열인 경우 op + gavin의 방법과 동일하지 않습니다. 이 경우 벡터로 변환되는 반면 op는 여전히 데이터 프레임입니다.
themartinmcfly 2013

1
tidyverse로 작업하는 사람들을 위해 : 흥미롭게도, 이것은 객체가 또한 tibble 일 때 작동하지 않는 것 같습니다. 코드는 다음 이후에 실패합니다Df <- tibble::as_tibble(Df)
Tjebo

1
@Tjebo는 tibble의 업데이트와 tibbles와 데이터 프레임 간의 전환으로 인해이 오래된 접근 방식은 실제로 tidyverse에서 최선의 선택이 아닙니다. 와 함께 tidyselect 기능을 사용하는 것이 좋습니다 mutate_if. 또는 다음 반복에서 사용할 수있는 새로운 접근 방식이 무엇이든 dplyr...
Joris Meys

30

나는이 질문이 오랫동안 해결되었음을 알고 있지만 최근 비슷한 문제가 있었고 magrittr 패키지가 필요하지만 조금 더 우아하고 기능적인 솔루션을 찾은 것 같습니다.

library(magrittr)
cols = c(1, 3, 4, 5)
df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))

그만큼 %<>%조작 파이프 유지 데이터 세정하고 간단한 변환 매우 유용 다시 할당. 이제 적용하려는 기능 만 지정하면 목록 적용 기능을 훨씬 쉽게 읽을 수 있습니다.


2
깔끔한 솔루션. 괄호 하나를 잊어 df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))
버렸지 만

1
df[,cols] %<>% as.numeric(as.character(.))똑같은 일 을 lappy로 포장 할 필요조차 없다고 생각합니다
Nate

내가이 명령을하려고 할 때 다음과 같은 오류 얻을Error in [.data.table(Results, , cols) : j (the 2nd argument inside [...]) is a single symbol but column name 'cols' is not found. Perhaps you intended DT[,..cols] or DT[,cols,with=FALSE]. This difference to data.frame is deliberate and explained in FAQ 1.1.
Urvah의 Shabbir

코드는 다음과 같습니다.cols <- c("a","b"); df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))
Urvah Shabbir

이제 브래킷이 추가되었습니다.

9

다음은 몇 가지 dplyr옵션입니다.

# by column type:
df %>% 
  mutate_if(is.factor, ~as.numeric(as.character(.)))

# by specific columns:
df %>% 
  mutate_at(vars(x, y, z), ~as.numeric(as.character(.))) 

# all columns:
df %>% 
  mutate_all(~as.numeric(as.character(.))) 

6

ucfagls가 이유찾았다 고 생각합니다 가 루프가 작동하지 않는 .

여전히 루프를 사용하고 싶지 않은 경우 다음과 lapply같은 솔루션이 있습니다 .

factorToNumeric <- function(f) as.numeric(levels(f))[as.integer(f)] 
cols <- c(1, 3:ncol(stats))
stats[cols] <- lapply(stats[cols], factorToNumeric)

편집하다. 더 간단한 해결책을 찾았습니다. as.matrix캐릭터로 변신하는 것 같습니다 . 그래서

stats[cols] <- as.numeric(as.matrix(stats[cols]))

당신이 원하는 것을해야합니다.


5

lapply는 이것을 위해 거의 설계되었습니다.

unfactorize<-c("colA","colB")
df[,unfactorize]<-lapply(unfactorize, function(x) as.numeric(as.character(df[,x])))

@transcom 안녕하세요. stackoverflow에 오신 것을 환영합니다. 이 질문은 그 반대가 아니라 요인에서 숫자 표현으로 변환하는 것에 관한 것입니다. Marek의 솔루션을 참조하십시오.
아론은 스택 오버플로를 왼쪽

@Aaron, 이해했습니다. 나는 OP 제목의 모호성으로 인해 다른 사람들이 클래스에 관계없이 여러 열을 쉽게 변환하는 방법을 찾고 여기에 착륙 할 수 있다는 가정 하에이 답변을 게시했습니다. 어쨌든, 나는 질문을 더 적절하게 해결하기 위해 내 대답을 편집했습니다 :)
transcom

2

이 기능은 몇 개의 다른 중복 스레드에서 발견되었으며이 문제를 해결하는 우아하고 일반적인 방법이라는 것을 알았습니다. 이 스레드는이 주제에 대한 대부분의 검색에서 가장 먼저 표시되므로 시간을 절약하기 위해 여기에서 공유하고 있습니다. 나는 이것에 대해 인정하지 않으므로 자세한 내용은 여기여기 에서 원본 게시물 을 참조하십시오.

df <- data.frame(x = 1:10,
                 y = rep(1:2, 5),
                 k = rnorm(10, 5,2),
                 z = rep(c(2010, 2012, 2011, 2010, 1999), 2),
                 j = c(rep(c("a", "b", "c"), 3), "d"))

convert.magic <- function(obj, type){
  FUN1 <- switch(type,
                 character = as.character,
                 numeric = as.numeric,
                 factor = as.factor)
  out <- lapply(obj, FUN1)
  as.data.frame(out)
}

str(df)
str(convert.magic(df, "character"))
str(convert.magic(df, "factor"))
df[, c("x", "y")] <- convert.magic(df[, c("x", "y")], "factor")

1

열에 NA가있는 경우 단순히 아래 첨자를 사용하면 작동하지 않는다는 점을 지적하고 싶습니다. 요인에 NA가있는 경우 Ramnath에서 제공하는 적용 스크립트를 사용해야합니다.

Df <- data.frame(
  x = c(NA,as.factor(sample(1:5,30,r=T))),
  y = c(NA,as.factor(sample(1:5,30,r=T))),
  z = c(NA,as.factor(sample(1:5,30,r=T))),
  w = c(NA,as.factor(sample(1:5,30,r=T)))
)

Df[,c(1:4)] <- as.numeric(as.character(Df[,c(1:4)]))

다음을 반환합니다.

Warning message:
NAs introduced by coercion 

    > head(Df)
       x  y  z  w
    1 NA NA NA NA
    2 NA NA NA NA
    3 NA NA NA NA
    4 NA NA NA NA
    5 NA NA NA NA
    6 NA NA NA NA

그러나:

Df[,c(1:4)]= apply(Df[,c(1:4)], 2, function(x) as.numeric(as.character(x)))

보고:

> head(Df)
   x  y  z  w
1 NA NA NA NA
2  2  3  4  1
3  1  5  3  4
4  2  3  4  1
5  5  3  5  5
6  4  2  4  4

1

unfactor()"varhandle"패키지 양식 CRAN의 함수를 사용할 수 있습니다 .

library("varhandle")

my_iris <- data.frame(Sepal.Length = factor(iris$Sepal.Length),
                      sample_id = factor(1:nrow(iris)))

my_iris <- unfactor(my_iris)

1

이 코드는 매우 편리하기 때문에 좋아합니다.

  data[] <- lapply(data, function(x) type.convert(as.character(x), as.is = TRUE)) #change all vars to their best fitting data type

정확히 무엇을 요청했는지 (숫자로 변환)는 아니지만 많은 경우에 더 적절합니다.


1

df$colname <- as.numeric(df$colname)

하나의 열 유형을 변경하기 위해이 방법을 시도했으며 모든 열 유형을 변경하지 않으려는 경우 다른 많은 버전보다 낫다고 생각합니다.

df$colname <- as.character(df$colname)

그 반대의 경우도 마찬가지입니다.


0

apply()호출 을 통해 모든 열을 숫자로 변환하는 데 문제가 있습니다 .

apply(data, 2, as.numeric)

문제는 일부 문자열에 쉼표가 포함되어 있기 때문입니다 (예 : "1024.63"대신 "1,024.63"). R은 이러한 숫자 형식 지정 방식을 좋아하지 않습니다. 그래서 나는 그들을 제거한 다음 실행했습니다 as.numeric().

data = as.data.frame(apply(data, 2, function(x) {
  y = str_replace_all(x, ",", "") #remove commas
  return(as.numeric(y)) #then convert
}))

이를 위해서는 stringr 패키지를로드해야합니다.


0

그것이 나를 위해 일한 것입니다. 이 apply()함수는 df를 행렬로 강제 변환하려고 시도하고 NA를 반환합니다.

numeric.df <- as.data.frame(sapply(df, 2, as.numeric))


0

@SDahm의 답변에 따르면 이것은 내 "최적의"솔루션이었습니다 tibble.

data %<>% lapply(type.convert) %>% as.data.table()

여기에는 dplyrmagrittr.


0

나는 비슷한 문제에 대해 이것들을 시도하고 NA를 계속 얻었습니다. Base R에는 일반적으로 Tidyverse 패키지에서 수정되는 몇 가지 정말 짜증나는 강제 동작이 있습니다. 종속성을 만들고 싶지 않았기 때문에 피하곤했지만 삶 을 훨씬 더 쉽게 만듭니다. 만들어 이제는 대부분의 시간 동안 Base R 솔루션을 알아 내려고 노력하지도 않습니다.

다음은 매우 간단하고 우아한 Tidyverse 솔루션입니다.

library(purrr)

mydf <- data.frame(
  x1 = factor(c(3, 5, 4, 2, 1)),
  x2 = factor(c("A", "C", "B", "D", "E")),
  x3 = c(10, 8, 6, 4, 2))

map_df(mydf, as.numeric)

대부분의 답변 (적어도 모든 상위 답변)은 숫자 값 대신 정수 수준이 너무 흔하게 변환 as.numeric(as.character())되지 않도록 변환을 수행해야합니다 . 해당 옵션을 표시하면이 답변을 기꺼이 찬성하겠습니다.
Gregor Thomas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.