Каков самый быстрый / лучший способ изменить большое количество столбцов на числовое с фактора?
Я использовал следующий код, но, похоже, он изменил порядок моих данных.
> 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)
Ответы:
В дополнение к ответу Рамната поведение, которое вы испытываете, связано с
as.numeric(x)
возвращением внутреннего числового представления фактораx
на уровне R. Если вы хотите сохранить числа, которые являются уровнями фактора (а не их внутренним представлением), вам необходимоas.character()
сначала преобразовать в символ через, как в примере Рамнатха.Ваш
for
цикл так же разумен, как иapply
вызов, и может быть немного более читаемым в зависимости от цели кода. Просто измените эту строку:stats[,i] <- as.numeric(stats[,i])
читать
stats[,i] <- as.numeric(as.character(stats[,i]))
Это FAQ 7.10 в R FAQ.
HTH
источник
factor
но это не сработало.sapply
илиmutate_if
кажутся более применимыми решениями.apply
для запуска цикла, а OPfor
явно использовал цикл. Фактически, все получившие большое количество голосов ответы используют этуas.numeric(as.character())
идиому.numeric
, но он не работает в обратном порядке (чтобы изменить класс нескольких столбцов наfactor
). Если вы используете нужные индексыunlist()
и при применении к столбцам с символами, он выводит из списка каждый отдельный символ, из-за чего он больше не работает при возврате вывода вstats[,i]
. Проверьте ответ здесь: stackoverflow.com/questions/45713473/…as.factor()
вместо этого,as.numeric(as.character())
и он будет работать нормально. Конечно, если у вас есть несколько столбцов, вам нужно выбиратьi
выборочно, но это тоже тривиально.Вы должны быть осторожны при замене множителей на числовые. Вот строка кода, которая изменит набор столбцов с факторного на числовой. Я предполагаю, что столбцы, которые нужно изменить на числовые, - это 1, 3, 4 и 5 соответственно. Вы можете изменить это соответствующим образом
cols = c(1, 3, 4, 5); df[,cols] = apply(df[,cols], 2, function(x) as.numeric(as.character(x)));
источник
x<-as.factor(1:3); df<-data.frame(a=x,y=runif(3),b=x,c=x,d=x)
. Я не думаю, чтоapply
это уместно для такого рода проблем.apply
. Проверьте мою правку.unlist
. Иas.character
преобразования в вашем решении не требуется причинноapply
обращенныхdf[,cols]
кcharacter
такapply(df[,cols], 2, function(x) as.numeric(x))
тоже будет работать.=
? Почему бы и нет<-
?Это можно сделать в одной строке, нет необходимости в цикле, будь то цикл 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])))
Очевидно, что если у вас есть фрейм данных с одним столбцом и вы не хотите, чтобы автоматическое уменьшение размера R преобразовывало его в вектор, вам придется добавить
drop=FALSE
аргумент.источник
recursive
иuse.names
параметровunlist
обоихFALSE
.Df <- tibble::as_tibble(Df)
mutate_if
. Или любой новый подход, который будет доступен в следующей итерацииdplyr
...Я знаю, что этот вопрос давно решен, но недавно у меня была аналогичная проблема, и я думаю, что нашел более элегантное и функциональное решение, хотя для этого требуется пакет magrittr.
library(magrittr) cols = c(1, 3, 4, 5) df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))
В
%<>%
оператор трубы и переназначает, что очень полезно для очистки данных учета и трансформации просто. Теперь функцию применения списка намного легче читать, поскольку здесь указывается только функция, которую вы хотите применить.источник
df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))
df[,cols] %<>% as.numeric(as.character(.))
работает то же самое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.
cols <- c("a","b"); df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))
Вот несколько
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(.)))
источник
Думаю, 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")
источник
Хочу отметить, что если у вас есть NA в любом столбце, просто использовать индексы не получится. Если в факторе есть НА, вы должны использовать сценарий применения, предоставленный Рамнатхом.
Например
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
источник
вы можете использовать
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)
источник
Мне нравится этот код, потому что он очень удобен:
data[] <- lapply(data, function(x) type.convert(as.character(x), as.is = TRUE)) #change all vars to their best fitting data type
Это не совсем то, что просили (преобразовать в число), но во многих случаях даже более подходящее.
источник
df$colname <- as.numeric(df$colname)
Я пробовал таким способом изменить один тип столбца и считаю, что он лучше, чем многие другие версии, если вы не собираетесь менять все типы столбцов.
df$colname <- as.character(df$colname)
для наоборот.
источник
У меня возникли проблемы с преобразованием всех столбцов в числовые с помощью
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()
функции пытается принудить ФР к матричным и возвращает НС.numeric.df <- as.data.frame(sapply(df, 2, as.numeric))
источник
Основываясь на ответе @SDahm, это было "оптимальное" решение для меня
tibble
:Для этого требуется
dplyr
иmagrittr
.источник
Я попробовал несколько из них по аналогичной проблеме и продолжал получать 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())
преобразование, чтобы избежать слишком распространенного преобразования целочисленных уровней вместо значений в числовые. Я с радостью проголосую за этот ответ, если вы покажете этот вариант.