Data.tableの使用に問題があります:列クラスを変換するにはどうすればよいですか?以下に簡単な例を示します。data.frameでは変換に問題はありませんが、data.tableでは方法がわかりません。
df <- data.frame(ID=c(rep("A", 5), rep("B",5)), Quarter=c(1:5, 1:5), value=rnorm(10))
#One way: http://stackoverflow.com/questions/2851015/r-convert-data-frame-columns-from-factors-to-characters
df <- data.frame(lapply(df, as.character), stringsAsFactors=FALSE)
#Another way
df[, "value"] <- as.numeric(df[, "value"])
library(data.table)
dt <- data.table(ID=c(rep("A", 5), rep("B",5)), Quarter=c(1:5, 1:5), value=rnorm(10))
dt <- data.table(lapply(dt, as.character), stringsAsFactors=FALSE)
#Error in rep("", ncol(xi)) : invalid 'times' argument
#Produces error, does data.table not have the option stringsAsFactors?
dt[, "ID", with=FALSE] <- as.character(dt[, "ID", with=FALSE])
#Produces error: Error in `[<-.data.table`(`*tmp*`, , "ID", with = FALSE, value = "c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)") :
#unused argument(s) (with = FALSE)
ここで明らかな何かを見逃していますか?
Matthewの投稿による更新:以前は古いバージョンを使用していましたが、1.6.6(現在使用しているバージョン)に更新した後でもエラーが発生します。
更新2:クラス「ファクター」のすべての列を「文字」列に変換したいとしますが、どの列がどのクラスのものかを事前に知りません。 data.frameを使用すると、次のことができます。
classes <- as.character(sapply(df, class))
colClasses <- which(classes=="factor")
df[, colClasses] <- sapply(df[, colClasses], as.character)
Data.tableで同様のことができますか?
アップデート3:
sessionInfo()Rバージョン2.13.1(2011-07-08)プラットフォーム:x86_64-pc-mingw32/x64(64ビット)
locale:
[1] C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] data.table_1.6.6
loaded via a namespace (and not attached):
[1] tools_2.13.1
単一の列の場合:
dtnew <- dt[, Quarter:=as.character(Quarter)]
str(dtnew)
Classes ‘data.table’ and 'data.frame': 10 obs. of 3 variables:
$ ID : Factor w/ 2 levels "A","B": 1 1 1 1 1 2 2 2 2 2
$ Quarter: chr "1" "2" "3" "4" ...
$ value : num -0.838 0.146 -1.059 -1.197 0.282 ...
lapply
およびas.character
の使用:
dtnew <- dt[, lapply(.SD, as.character), by=ID]
str(dtnew)
Classes ‘data.table’ and 'data.frame': 10 obs. of 3 variables:
$ ID : Factor w/ 2 levels "A","B": 1 1 1 1 1 2 2 2 2 2
$ Quarter: chr "1" "2" "3" "4" ...
$ value : chr "1.487145280568" "-0.827845218358881" "0.028977182770002" "1.35392750102305" ...
これを試して
DT <- data.table(X1 = c("a", "b"), X2 = c(1,2), X3 = c("hello", "you"))
changeCols <- colnames(DT)[which(as.vector(DT[,lapply(.SD, class)]) == "character")]
DT[,(changeCols):= lapply(.SD, as.factor), .SDcols = changeCols]
Geneoramaの答え(- https://stackoverflow.com/a/20808945/424178 )へのMatt Dowleのコメントを上げて、より明確にする(推奨)。
for (col in names_factors)
set(dt, j=col, value=as.factor(dt[[col]]))
また、Mattの別のコメントで、詳細については https://stackoverflow.com/a/33000778/424178 を参照してください。
これは悪い方法です!この答えは、他の奇妙な問題を解決する場合にのみ残します。これらのより良いメソッドは、おそらく部分的には新しいdata.tableバージョンの結果です...したがって、この難しい方法を文書化する価値はあります。さらに、これはeval
substitute
構文のニース構文例です。
library(data.table)
dt <- data.table(ID = c(rep("A", 5), rep("B",5)),
fac1 = c(1:5, 1:5),
fac2 = c(1:5, 1:5) * 2,
val1 = rnorm(10),
val2 = rnorm(10))
names_factors = c('fac1', 'fac2')
names_values = c('val1', 'val2')
for (col in names_factors){
e = substitute(X := as.factor(X), list(X = as.symbol(col)))
dt[ , eval(e)]
}
for (col in names_values){
e = substitute(X := as.numeric(X), list(X = as.symbol(col)))
dt[ , eval(e)]
}
str(dt)
あなたに与える
Classes ‘data.table’ and 'data.frame': 10 obs. of 5 variables:
$ ID : chr "A" "A" "A" "A" ...
$ fac1: Factor w/ 5 levels "1","2","3","4",..: 1 2 3 4 5 1 2 3 4 5
$ fac2: Factor w/ 5 levels "2","4","6","8",..: 1 2 3 4 5 1 2 3 4 5
$ val1: num 0.0459 2.0113 0.5186 -0.8348 -0.2185 ...
$ val2: num -0.0688 0.6544 0.267 -0.1322 -0.4893 ...
- attr(*, ".internal.selfref")=<externalptr>
このことを行うためのより一般的で安全な方法を提供しますが、
".." <- function (x)
{
stopifnot(inherits(x, "character"))
stopifnot(length(x) == 1)
get(x, parent.frame(4))
}
set_colclass <- function(x, class){
stopifnot(all(class %in% c("integer", "numeric", "double","factor","character")))
for(i in intersect(names(class), names(x))){
f <- get(paste0("as.", class[i]))
x[, (..("i")):=..("f")(get(..("i")))]
}
invisible(x)
}
関数..
は、data.tableのスコープ外の変数を確実に取得します。 set_colclassは、colsのクラスを設定します。次のように使用できます。
dt <- data.table(i=1:3,f=3:1)
set_colclass(dt, c(i="character"))
class(dt$i)
いくつかのアプローチを試しました。
# BY {dplyr}
data.table(ID = c(rep("A", 5), rep("B",5)),
Quarter = c(1:5, 1:5),
value = rnorm(10)) -> df1
df1 %<>% dplyr::mutate(ID = as.factor(ID),
Quarter = as.character(Quarter))
# check classes
dplyr::glimpse(df1)
# Observations: 10
# Variables: 3
# $ ID (fctr) A, A, A, A, A, B, B, B, B, B
# $ Quarter (chr) "1", "2", "3", "4", "5", "1", "2", "3", "4", "5"
# $ value (dbl) -0.07676732, 0.25376110, 2.47192852, 0.84929175, -0.13567312, -0.94224435, 0.80213218, -0.89652819...
、 もしくはそうでないか
# from list to data.table using data.table::setDT
list(ID = as.factor(c(rep("A", 5), rep("B",5))),
Quarter = as.character(c(1:5, 1:5)),
value = rnorm(10)) %>% setDT(list.df) -> df2
class(df2)
# [1] "data.table" "data.frame"