382

私はデータフレームを持っています。彼を呼びましょう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)"

私はこれを理解し始めていませんが、これらはbob? 私が必要とするものではありません。

奇妙なことに、私はbob手で列を通り抜けることができます。

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

これは正常に動作します。そして、いくつか入力した後、列が因子ではなく文字である data.frame を取得できます。だから私の質問は:どうすればこれを自動的に行うことができますか? 各列を手動で処理することなく、factor 列を持つ data.frame を character 列を持つ data.frame に変換するにはどうすればよいですか?

おまけの質問: 手動のアプローチが機能するのはなぜですか?

4

18 に答える 18

383

Matt と Dirk をフォローするだけです。グローバル オプションを変更せずに既存のデータ フレームを再作成する場合は、apply ステートメントを使用して再作成できます。

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

これにより、すべての変数がクラス「文字」に変換されます。因子のみを変換する場合は、以下のマレクのソリューションを参照してください。

@hadley が指摘するように、以下はより簡潔です。

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

どちらの場合もlapplyリストを出力します。ただし、R の魔法の特性により[]、2 番目のケースで を使用すると、オブジェクトの data.frame クラスが保持されるため、引数bobを使用して data.frame に戻す必要がなくなります。as.data.framestringsAsFactors = FALSE

于 2010-05-17T17:21:06.727 に答える
334

因子のみを置換するには:

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

バージョン 0.5.0 のパッケージ dplyrでは、新しい機能mutate_ifが導入されました

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

...そしてバージョン 1.0.0 では次のように置き換えられましたacross:

library(dplyr)
bob %>% mutate(across(where(is.factor), as.character)) -> bob

RStudio のパッケージ purrrは、別の代替手段を提供します。

library(purrr)
bob %>% modify_if(is.factor, as.character) -> bob
于 2010-05-17T22:08:48.400 に答える
41

グローバルオプション

stringsAsFactors: data.frame および read.table の引数のデフォルト設定。

FALSE起動ファイル (例: ~/.Rprofile) で設定したいものかもしれません。をご覧くださいhelp(options)

于 2010-05-17T17:02:36.193 に答える
25

因子がどのように格納されるかを理解していれば、適用ベースの関数を使用してこれを達成することを避けることができます。これは、適用ソリューションがうまく機能しないことを意味するものではありません。

因子は、「レベル」のリストに関連付けられた数値インデックスとして構造化されています。これは、係数を数値に変換するとわかります。そう:

> 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
于 2013-03-21T17:40:06.170 に答える
21

のすべての因子ベクトルが文字ベクトルに変換される新しいデータフレームbobcが必要な場合は、次のことを試してください。bobf

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

その後、それを元に戻したい場合は、列が因子である論理ベクトルを作成し、それを使用して因子を選択的に適用できます。

f <- sapply(bobf, class) == "factor"
bobc[,f] <- lapply(bobc[,f], factor)
于 2012-01-05T06:04:58.457 に答える
14

私は通常、この機能をすべてのプロジェクトから切り離しています。早くて簡単。

unfactorize <- function(df){
  for(i in which(sapply(df, class) == "factor")) df[[i]] = as.character(df[[i]])
  return(df)
}
于 2013-01-10T22:25:09.257 に答える
10

別の方法は、適用を使用して変換することです

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

そしてより良いもの(前のものはクラス「マトリックス」のものです)

bob2 <- as.data.frame(as.matrix(bob),stringsAsFactors=F)
于 2010-05-17T17:15:18.973 に答える
8

更新: これは、うまくいかない例です。私はそうなると思っていましたが、stringAsFactors オプションは文字列でのみ機能すると思います - それは要因をそのままにしておきます。

これを試して:

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

一般的に言えば、文字であるべき要素に問題がある場合はいつでも、stringsAsFactorsどこかに役立つ設定があります (グローバル設定を含む)。

于 2010-05-17T17:00:21.460 に答える
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ますが、好きなことは何でもできますが、「歩行者スタイルのコード作成」が犠牲になります...

そこで... =)

于 2010-05-17T17:49:17.017 に答える
2

これは私にとってはうまくいきます-私はついにワンライナーを考え出しました

df <- as.data.frame(lapply(df,function (y) if(class(y)=="factor" ) as.character(y) else y),stringsAsFactors=F)
于 2014-10-24T16:00:22.063 に答える
1

この関数はトリックを行います

df <- stacomirtools::killfactor(df)
于 2017-11-13T16:46:28.410 に答える