data.frame 열을 인수에서 문자로 변환


352

데이터 프레임이 있습니다. 전화 해 봅시다 bob:

> head(bob)
                 phenotype                         exclusion
GSM399350 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399351 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399352 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399353 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399354 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399355 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-

이 데이터 프레임의 행을 연결하고 싶습니다 (또 다른 질문이 될 것입니다). 그러나보세요 :

> class(bob$phenotype)
[1] "factor"

Bob의 열은 요인입니다. 예를 들어,

> as.character(head(bob))
[1] "c(3, 3, 3, 6, 6, 6)"       "c(3, 3, 3, 3, 3, 3)"      
[3] "c(29, 29, 29, 30, 30, 30)"

나는 이것을 이해하기 시작하지 않지만, 이것들이 (Caractacus 왕의 법원의) 기둥의 요인 수준에 대한 지표라고 생각 bob합니까? 내가 필요한 것은 아닙니다.

이상하게도 나는 bob손으로 기둥을 통과 할 수 있고

bob$phenotype <- as.character(bob$phenotype)

잘 작동합니다. 그리고 일부 입력 한 후 열이 요인이 아닌 문자 인 data.frame을 얻을 수 있습니다. 그래서 내 질문은 : 어떻게 자동으로 할 수 있습니까? 요인 열이있는 data.frame을 각 열을 수동으로 거치지 않고 문자 열이있는 data.frame으로 변환하는 방법은 무엇입니까?

보너스 질문 : 왜 수동 접근 방식이 작동합니까?


3
질문을 재현 가능하게 만들면 좋을 것이므로의 구조를 포함하십시오 bob.
jangorecki

답변:


362

Matt와 Dirk을 팔로우합니다. 글로벌 옵션을 변경하지 않고 기존 데이터 프레임을 다시 작성하려면 apply 문을 사용하여 해당 데이터 프레임을 다시 작성할 수 있습니다.

bob <- data.frame(lapply(bob, as.character), stringsAsFactors=FALSE)

인자 만 변환하려면 아래의 Marek 솔루션을 참조하십시오 .

@hadley가 지적했듯이 다음은 더 간결합니다.

bob[] <- lapply(bob, as.character)

두 경우 모두 lapply목록을 출력합니다. 그러나 R의 마법 속성으로 인해 []두 번째 경우를 사용 하면 bob객체 의 data.frame 클래스가 유지 as.data.frame되므로 인수를 사용하여 data.frame으로 다시 변환 할 필요가 없습니다 stringsAsFactors = FALSE.


27
셰인, 그것은 또한 숫자 열을 문자로 바꿀 것입니다.
Dirk Eddelbuettel

@ Dirk : 그것이 문제인지는 확실하지 않지만 사실입니다. 분명히, 물건을 올바르게 만드는 것이 최선의 해결책입니다. 데이터 프레임에서 데이터 유형을 자동으로 쉽게 변환 할 있다고 생각하지 않습니다 . 하나의 옵션은 위의를 사용하지만 사용하는 것입니다 type.convert이르기까지 모든 캐스팅 후 character참 -_- 다음, factors다시로 character다시.
셰인

이것은 행 이름을 버리는 것 같습니다.
piccolbo

2
@piccolbo bob[] <- 예제에서 사용 했 bob <- 습니까? 첫 번째는 data.frame을 유지합니다. 두 번째는 data.frame을 목록으로 변경하여 행 이름을 삭제합니다. 답을 업데이트하겠습니다
David LeBauer

6
익명 함수를 사용하여 요인 열만 문자로 변환하는 변형 : iris[] <- lapply(iris, function(x) if (is.factor(x)) as.character(x) else {x})
Stefan F

313

요인 만 바꾸려면

i <- sapply(bob, is.factor)
bob[i] <- lapply(bob[i], as.character)

버전 0.5.0의mutate_if 패키지 dplyr 에는 새로운 기능 이 도입되었습니다 .

library(dplyr)
bob %>% mutate_if(is.factor, as.character) -> bob

RStudio의 패키지 purrr 는 또 다른 대안을 제공합니다.

library(purrr)
library(dplyr)
bob %>% map_if(is.factor, as.character) %>% as_tibble -> bob

슬프게도 나를 위해 일하지 않습니다. 이유를 모릅니다. 아마도 내가 이름을 가지고 있기 때문에?
Autumnsault

@mohawkjohn 문제가되지 않아야합니다. 예상치 못한 오류나 결과가 있습니까?
Marek

2
참고 :이 purrr줄은 data.frame!가 아닌 목록을 반환합니다 .
RoyalTS

이미가 i벡터 인 경우에도 작동합니다 colnames().
verbamour

39

글로벌 옵션

stringsAsFactors : data.frame 및 read.table의 인수에 대한 기본 설정입니다.

FALSE시작 파일에서 설정하려는 것이 될 수 있습니다 (예 : ~ / .Rprofile). 참조하십시오 help(options).


5
이 문제는 .Rprofile 파일이없는 환경에서 코드를 실행할 때 버그가 발생한다는 것입니다!
웨이퍼 씬

4
설정이 .Rprofile에있는 것이 아니라 스크립트의 시작 부분에 호출하는 경향이 있습니다.
gregmacfarlane

22

요인이 저장되는 방식을 이해하면 적용 기반 함수를 사용하여이를 수행하지 않아도됩니다. 적용 솔루션이 제대로 작동하지 않는다는 의미는 아닙니다.

요인은 '수준'목록에 연결된 숫자 색인으로 구성됩니다. 요인을 숫자로 변환하면 볼 수 있습니다. 그래서:

> fact <- as.factor(c("a","b","a","d")
> fact
[1] a b a d
Levels: a b d

> as.numeric(fact)
[1] 1 2 1 3

마지막 줄에 반환 된 숫자는 요인의 수준에 해당합니다.

> levels(fact)
[1] "a" "b" "d"

levels()문자 배열 을 반환합니다. 이 사실을 사용하여 다음과 같이 요인을 문자열 또는 숫자로 쉽고 간단하게 변환 할 수 있습니다.

> fact_character <- levels(fact)[as.numeric(fact)]
> fact_character
[1] "a" "b" "a" "d"

에서 식을 래핑하면 숫자 값에도 적용됩니다 as.numeric().

> num_fact <- factor(c(1,2,3,6,5,4))
> num_fact
[1] 1 2 3 6 5 4
Levels: 1 2 3 4 5 6
> num_num <- as.numeric(levels(num_fact)[as.numeric(num_fact)])
> num_num
[1] 1 2 3 6 5 4

이 답변은 문제를 해결하지 못합니다 . 데이터 프레임의 모든 요인 열을 문자 로 변환하는 방법 입니다. as.character(f)가독성과 효율성이 모두 우수합니다 levels(f)[as.numeric(f)]. 영리하고 싶었다면 levels(f)[f]대신 사용할 수 있습니다 . 숫자 값을 가진 요인을 변환 할 때 as.numeric(levels(f))[f], 예를 들어, as.numeric(as.character(f))과 같은 이점 이 있지만 레벨을 숫자로 변환 한 다음 부분 집합 만 변환하면되기 때문입니다. as.character(f)그대로 괜찮습니다.
De Novo

20

새로운 데이터 프레임하려면 모든 의 요소 벡터 IS는 문자 벡터로 변환을,이 시도 :bobcbobf

bobc <- rapply(bobf, as.character, classes="factor", how="replace")

그런 다음 다시 변환하려면 열이 요인 인 논리 벡터를 만들고이를 사용하여 선택적으로 요인을 적용 할 수 있습니다

f <- sapply(bobf, class) == "factor"
bobc[,f] <- lapply(bobc[,f], factor)

2
필요한 것만 수행하기 위해 +1 (즉, 전체 data.frame을 문자로 변환하지 않음) 이 솔루션은 혼합 유형이 포함 된 data.frame에 강력합니다.
Joshua Ulrich

3
이 예제는 stat.ethz.ch/R-manual/R-devel/library/base/html/rapply.html과 같이 rapply에 대한`Examples '섹션에 있어야 합니다. 그것을 요구하는 방법을 아는 사람이 있습니까?
mpettis 2013 년

데이터 프레임으로 끝내려면, 간단하게 data.frame 호출에서 랩을 랩핑하십시오 (stringsAsFactors가 FALSE 인수로 설정 됨)
Taylored Web Sites

13

나는 일반적으로이 기능을 모든 프로젝트와 별도로 만듭니다. 빠르고 쉽습니다.

unfactorize <- function(df){
  for(i in which(sapply(df, class) == "factor")) df[[i]] = as.character(df[[i]])
  return(df)
}

8

다른 방법은 apply를 사용하여 변환하는 것입니다

bob2 <- apply(bob,2,as.character)

그리고 더 좋은 것 (이전의 클래스는 '행렬'입니다)

bob2 <- as.data.frame(as.matrix(bob),stringsAsFactors=F)

as.data.frame(lapply(...
@Shane

7

업데이트 : 작동하지 않는 예가 있습니다. 필자는 생각했지만 stringsAsFactors 옵션은 문자열에서만 작동한다고 생각합니다. 인수는 그대로 둡니다.

이 시도:

bob2 <- data.frame(bob, stringsAsFactors = FALSE)

일반적으로 캐릭터가되어야하는 요소에 문제가있을 때마다 stringsAsFactors전역 설정을 포함하여 도움을 줄 수있는 설정이 있습니다.


1
그가 처음으로 만들 때 설정하면 작동 bob하지만 실제로는 아닙니다.
Shane

권리. 이것이 문제 자체를 해결하지 못한다는 점을 분명히하기를 원했지만 문제를 방지한다는 점에 감사드립니다.
매트 파커

7

또는 시도해 볼 수 있습니다 transform:

newbob <- transform(bob, phenotype = as.character(phenotype))

문자로 변환하려는 모든 요소를 ​​입력하십시오.

또는 이런 식으로 한 번의 타격으로 모든 해충을 죽일 수 있습니다.

newbob_char <- as.data.frame(lapply(bob[sapply(bob, is.factor)], as.character), stringsAsFactors = FALSE)
newbob_rest <- bob[!(sapply(bob, is.factor))]
newbob <- cbind(newbob_char, newbob_rest)

그건 아니 , 내가 할 수있는이 같은 코드의 데이터를 밀어하는 좋은 생각 sapply나는 코드를 확인하지 않은 ..., (실제로, 그것은 그런 식으로 그것을하는 것이 훨씬 쉽다) 별도로 일부를하지만 당신은 요점을 파악, '원인 나는 집에 없어서 작동하기를 바랍니다! =)

그러나이 방법에는 단점이 있습니다. 나중에 컬럼을 재구성해야 transform하지만 원하는대로 무엇이든 할 수 있지만 "보행자 스타일 코드 작성" 비용이 발생합니다 .

그래서 거기에 ... =)


6

데이터 프레임의 시작 부분에 stringsAsFactors = FALSE모든 오해를 무시하십시오.


4

data.tabledata.frame의 작업에 패키지를 사용 하면 문제가 없습니다.

library(data.table)
dt = data.table(col1 = c("a","b","c"), col2 = 1:3)
sapply(dt, class)
#       col1        col2 
#"character"   "integer" 

이미 데이터 세트에 요인 열이 있고이를 문자로 변환하려는 경우 다음을 수행 할 수 있습니다.

library(data.table)
dt = data.table(col1 = factor(c("a","b","c")), col2 = 1:3)
sapply(dt, class)
#     col1      col2 
# "factor" "integer" 
upd.cols = sapply(dt, is.factor)
dt[, names(dt)[upd.cols] := lapply(.SD, as.character), .SDcols = upd.cols]
sapply(dt, class)
#       col1        col2 
#"character"   "integer" 

DT는 Marek이 제안한 Sapply 수정을 우회합니다 In [<-.data.table(*tmp*, sapply(bob, is.factor), : Coerced 'character' RHS to 'double' to match the column's type. Either change the target column to 'character' first (by creating a new 'character' vector length 1234 (nrows of entire table) and assign that; i.e. 'replace' column), or coerce RHS to 'double' (e.g. 1L, NA_[real|integer]_, as.*, etc) to make your intent clear and for speed. Or, set the column type correctly up front when you create the table and stick to it, please.. DF를 수정하고 DT를 더 쉽게 만들 수 있습니다.
Matt Chambers

2

이것은 나를 위해 작동합니다-나는 마침내 하나의 라이너를 계산했습니다.

df <- as.data.frame(lapply(df,function (y) if(class(y)=="factor" ) as.character(y) else y),stringsAsFactors=F)

2

이 기능은 트릭을 수행합니다

df <- stacomirtools::killfactor(df)

2

아마도 더 새로운 옵션일까요?

library("tidyverse")

bob <- bob %>% group_by_if(is.factor, as.character)

1

파이프 와 호환되는 읽을 수있는 구문을 제공 하는 convertin hablar을 사용해야합니다 tidyverse.

library(dplyr)
library(hablar)

df <- tibble(a = factor(c(1, 2, 3, 4)),
             b = factor(c(5, 6, 7, 8)))

df %>% convert(chr(a:b))

그것은 당신에게 제공합니다 :

  a     b    
  <chr> <chr>
1 1     5    
2 2     6    
3 3     7    
4 4     8   

1

dplyr-package가로드 된 상태에서

bob=bob%>%mutate_at("phenotype", as.character)

phenotype-column 만 변경하려는 경우


0

이것은 모두 문자로 변환 한 다음 숫자를 숫자로 변환합니다.

makenumcols<-function(df){
  df<-as.data.frame(df)
  df[] <- lapply(df, as.character)
  cond <- apply(df, 2, function(x) {
    x <- x[!is.na(x)]
    all(suppressWarnings(!is.na(as.numeric(x))))
  })
  numeric_cols <- names(df)[cond]
  df[,numeric_cols] <- sapply(df[,numeric_cols], as.numeric)
  return(df)
}

적응 : 엑셀 시트의 열 유형을 자동으로 가져옵니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.