Измените класс с factor на numeric для многих столбцов во фрейме данных
какой самый быстрый/лучший способ изменить большое количество столбцов с числовыми от фактора?
я использовал следующий код, но он, кажется, переупорядочил мои данные.
> 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)
11 ответов:
в дополнение к ответу Рамната, поведение, которое вы испытываете, связано с
as.numeric(x)возвращает внутреннее числовое представление фактораxна уровне Р. Если вы хотите сохранить числа, которые являются уровнями фактора (а не их внутренним представлением), вам нужно преобразовать в символ черезas.character()во-первых, согласно примеру Рамната.код
forцикл так же разумно, какapplyвызов и может быть немного более читаемым, чтобы в чем смысл этого кодекса. Просто измените эту строку:stats[,i] <- as.numeric(stats[,i])читать
stats[,i] <- as.numeric(as.character(stats[,i]))это FAQ 7.10 в R FAQ.
HTH
вы должны быть осторожны при изменении факторов в числовые. Вот строка кода, которая изменит набор столбцов с фактора на числовой. Я предполагаю, что столбцы, которые будут изменены на числовые, равны 1, 3, 4 и 5 соответственно. Вы можете изменить его соответствующим образом
cols = c(1, 3, 4, 5); df[,cols] = apply(df[,cols], 2, function(x) as.numeric(as.character(x)));
Это можно сделать в одной строке, нет необходимости в цикле, будь то for-loop или apply. Вместо этого используйте 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])))очевидно, что если у вас есть фрейм данных с одним столбцом, и вы не хотите, чтобы автоматическое уменьшение размера R преобразовывало его в вектор, вам придется добавить
Я знаю, что этот вопрос давно решен, но недавно у меня была аналогичная проблема, и думаю, что я нашел немного более элегантное и функциональное решение, хотя для этого требуется пакет magrittr.
library(magrittr) cols = c(1, 3, 4, 5) df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))The
%<>%оператор трубы и переназначения, что очень полезно для поддержания очистки данных и преобразования просто. Теперь список применить функцию гораздо легче читать, только указав функцию, которую вы хотите применить.
думаю, что 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]))должны делать то, что вы хотите.
lapply в значительной степени предназначен для этого
unfactorize<-c("colA","colB") df[,unfactorize]<-lapply(unfactorize, function(x) as.numeric(as.character(df[,x])))
Я нашел эту функцию на нескольких других повторяющихся потоках и нашел ее элегантным и общим способом решения этой проблемы. Эта тема появляется сначала в большинстве поисков по этой теме,поэтому я делюсь ею здесь, чтобы сэкономить время людей. Я не беру на себя ответственность за это просто так увидеть оригинальные сообщения здесь и здесь для сведения.
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")
Я хотел бы отметить, что если у вас есть NAs в любом столбце, просто с помощью индексов не будет работать. Если в факторе есть NAs, вы должны использовать сценарий apply, предоставленный 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
у меня были проблемы с преобразованием всех столбцов в числовые с помощью
apply()звоните:apply(data, 2, as.numeric)проблема оказывается в том, что некоторые строки имели запятую в них-например, "1,024.63" вместо "1024.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.
вот что сработало для меня. Элемент
apply()функция пытается принудить df к Матрице и возвращает NA.
numeric.df <- as.data.frame(sapply(df, 2, as.numeric))
можно использовать
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)
Comments